static关键字的理解
目录
1.static的含义与作用
2.static的用法
3.static的注意事项
1.static的含义与作用
static翻译为中文的意思是静态的,所以被static修饰的结构都被成为静态的XXX。static的作用大致如下:
(1)static可以去修饰代码块,用来形成静态代码块以优化程序的性能和解决在创建对象前就要完成需要做的准备工作的问题。
①静态代码块有一个特性是:只会在类加载的时候执行一次,所以很多时候会将一些只需要进行一次的初始化操作都放在静态代码块中,这样就优化了程序的性能,提高了执行效率。
②静态代码块可解决在创建对象前就要完成需要做的准备工作的问题,简单来说,就是当我们在创建对象之前需要做一些准备工作,这些准备工作都可以写在静态代码块内,比如连接数据库的时候,要提前加载JDBC的驱动,此时我们就可以把加载JDBC驱动的代码写在静态代码块内,静态代码块是随着类的加载而加载到内存中,要早于对象的创建,所以在连接数据库之前,在静态代码块内的加载JDBC的驱动的代码已经加载了,解决了此类问题。
(2)static修饰类的成员变量作为静态变量,被static修饰的变量独立于该类的任何对象,和对象无关!换句话说,该静态变量属于这个类,不属于任何一个对象,这个类的所有对象共享这个静态变量。作用:解决了窗口卖票的问题
举例:有三个窗口卖火车票,总票数是100张。这时,三个窗口就是三个对象,如果我们把火车票声明为类的一个成员变量的话,那么这三个窗口对象都拥有一套自己的100张票(对于某一个类的成员变量,该类的多个对象都拥有一套属于自己的成员变量),这时三个窗口总共卖出了300张票,不符合现实逻辑。当我们把火车票声明为静态变量的时候,这100张票就是三个窗口共享的变量,不属于任何一个具体的对象,这时三个窗口可卖出的总票数为100张。
(3)static修饰成员方法作为静态方法。在JavaAPI中的一些类是抽象类,是不能被实例化的,在不实现抽象类的前提下,可以把抽象类中的常用的公开的普通方法用static修饰,变为静态方法,这样就可以直接通过类名进行调用,完成我们需要的功能。
(4)static修饰内部类作为静态内部类。
静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:
1、它的创建是不需要依赖外围类的创建。
2、它不能使用任何外围类的非static成员变量和方法。
代码举例(静态内部类实现单例模式)
public class Singleton {// 声明为 private 避免调用默认构造方法创建对象private Singleton() {}// 声明为 private 表明静态内部该类只能在该 Singleton 类中被访问private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getUniqueInstance() {return SingletonHolder.INSTANCE;}
}
当 Singleton 类加载时,静态内部类 SingletonHolder 没有被加载进内存。只有当调用 getUniqueInstance()方法从而触发 SingletonHolder.INSTANCE 时 SingletonHolder 才会被加载,此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次。
这种方式不仅具有延迟初始化的好处,而且由 JVM 提供了对线程安全的支持。
2.static的用法
(1)static修饰成员变量: static 变量类型 变量名;
调用静态变量的两种方式:
类名.静态变量
对象.静态变量(不推荐)
(2)static修饰成员方法:权限修饰符 static 返回值类型 方法名(参数列表){方法体};
调用静态方法的两种方式:
类名.静态方法
对象.静态方法不推荐)
(3)static修饰代码块:static { }
(4)static修饰内部类:static 内部类名{ }
3.static的注意事项
(1)静态变量:
①静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。实例变量:每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。
②静态变量是随着类的加载而加载的优先于对象的创建
③分析内存:只要是static修饰的成员变量,都是在.class【字节码文件】文件,编译阶段,就直接加载到了内存的数据区。该过程是早于对象的创建的,整个数据区静态的成员属性是伴随着整个程序的结束而结束。
④保存区域:类对象的成员属性保存在堆区。 静态的成员属性则保存在数据区
(2)静态方法:
①静态的成员方法可以摆脱对象束缚,直接使用类名调用静态的成员方法
②内存分析:静态的成员方法随着.class文件的加载而加载。会被加载到方法区。这个时候方法的创建要早于对象的创建。
③静态的成员方法中不能使用非静态的成员属性和非静态的成员方法
④静态的方法不能被重写
⑤静态方法中可以创建对象
(3)静态代码块
①类只要一加载,静态代码块就一定加载
②静态代码块也是优先于对象的创建
③静态代码块的执行顺序优先于构造代码块和构造方法的
总之,静态只能访问静态的结构,
非静态既可以访问非静态结构,也可以访问静态结构。