在这里首先明确,静态static关键字和jvm虚拟机常量池是两个概念。
只是static关键字修饰常量或者变量,会在类实例化之前就放在常量池中而已。
static关键字
由static修饰的变量,常量和方法被称为静态变量,常量和方法。
final关键字
由final修改的为常量。由final和static共同修饰的为静态常量
如下:测试java中静态常量和静态变量区别的样例,表明两者加载时的区别。
StaticClass类中定义了静态常量FIANL_VALUE和静态变量VALUE,静态代码块的打印语句表示类被加载:
public class StaticClass {
static {
System.out.println("StaticClass loading...");
}
public static String VALUE = "static value loading";
public static final String FIANL_VALUE = "fianl value loading";
public static final int FINAL_VALUE_INT = new Random(66).nextInt();
}
StaticClassLoadTest类用于测试静态变量的加载:
public class StaticClassLoadTest {
public static void main(String[] args) {
System.out.println("StaticClassLoadTest...");
printStaticVar();
}
private static void printStaticVar() {
// System.out.println(StaticClass.FINAL_VALUE_INT);//这个因为是随机数,需要出发类加载
System.out.println(StaticClass.FIANL_VALUE); //这个因为是一个常量,不需要类加载就能得到
System.out.println(StaticClass.VALUE);
}
}
输出:
StaticClassLoadTest...
fianl value loading
StaticClass loading...
static value loading
输出显示在打印静态常量时,StaticVar类并没有被加载,在输出静态变量的前才打印类加载信息。这表明类的未加载的情况下也能引用其静态常量信息,原因是因为常量值存储在JVM内存中的常量区中,在类不加载时即可访问。
注:经过编译优化,静态常量FIANL_VALUE已经存到NotInit类自身常量池中,不会加载StaticClass
但是不能说所有的静态常用访问都不需要类的加载,这里还要判断这个常量是否属于“编译期常量”,即在编译期即可确定常量值。如果常量值必须在运行时才能确定,如常量值是一个随机值,也会引起类的加载,如下:
publicstaticfinalintFINAL_VALUE_INT =newRandom(66).nextInt();