本文参考《深入理解JAVA虚拟机》第2版,此书JDK版本为1.7。
java类的初始化阶段,虚拟机规范严格规定了5种情况必须立即对类进行初始化。
除了上述5种场景,其他所有类的方式都不会触发初始化,称为被动引用。下面举3个例子来说明。
public class SuperClass{
static {
System.out.println("SuperClass init!");
}
public static int value = 123;
}
public class SubClass extends SuperClass{
static {
System.out.println("SubClass init!");
}
}
public class InitTest{
public static void main(String[] args){
System.out.println(SubClass.value);
}
}
//执行结果
//SuperClass init!
//123
结论:对于静态变量,只有对应这个静态变量的类才会被初始化,通过子类调用只会使父类初始化,子类不会初始化。
public class InitTest{
public static void main(String[] args){
SuperClass[] array = new SuperClass[10];
}
}
//运行后没有输出
结论:创建对象数组不会使对象的类初始化。注:会使数组类初始化,在这个例子中,数组类是"[L包名.SuperClass"
public class ConstClass{
static {
System.out.println("ConstClass init!");
}
public static int value = 123;
}
public class InitTest{
public static void main(String[] args){
System.out.println(ConstClass.value);
}
}
//执行结果
//123
结论:调用对象常量不会触发类初始化。书中解释:在编译阶段通过常量传播优化,已经将此常量的值“123”存储到了InitTest类的常量池中,以后InitTest对常量ConstClass.value的引用实际都转换为InitTest对自身常量池的引用。