您的位置:首页 > 编程语言 > Java开发

java虚拟机规定必须立即初始化类的5种情况

2017-08-09 14:06 169 查看
Java类加载机制中,规定了有且仅有5种情况必须立即对类进行初始化(而加载,验证,准备自然再次之前):

1. 遇到new,getstatic,putstatic和invokestatic这4条指令时,如果类没有初始化时,必须初始化类。四条指令对应我们日常所见的 使用new关键字实例化对象,读取一个类的静态字段,设置一个类的静态字段(被final修饰的静态字段除外,因为已在编译期把结果放入常量池中了)和调用一个类的静态方法。

2. 对类进行反射调用时。

3. 当初始化一个子类时,发现其父类没有初始化,则需先出发其父类的初始化。

4. 当虚拟机启动时,一个类包含main()方法时,当前类需要初始化

5. 但是用动态语言支持时,如果一个java.lang.invoke.MethodHandle实例后解析结果REF_putStatic,REF_getStatic,REF_invokeStatic的方法句柄时,当改方法句柄对应的类没有初始化时,需要初始化该类。(动态语言支持详情请查看)

初次之外所有引用类的地方都不会出发类初始化,被称为被动应用,下面举三个例子:

1. 通过子类应用父类静态字段,不会导致子类初始化,代码如下:

package com.sun.jojo.noinitclass;
public class SuperClass {
static {
System.out.println("SuperClass Init !!!");
}
public static int value = 123;
}

package com.sun.jojo.noinitclass;
public class SubClass extends SuperClass{
static {
System.out.println("SubClass Init !!!");
}
}

package com.sun.jojo.noinitclass;
public class NotInitialization {
public static void main(String[] args) {
System.out.println(SubClass.value);
}
}


结果:

SuperClass Init !!!

123

结果只输出了”SuperClass Init !!!”, “SubClass Init !!!”没有出来,对应静态字段,只有直接定义改字段的类才会初始化。

2 .通过数组定义来引用类,不会出发此类的初始化,代码如下:

package com.sun.jojo.noinitclass;
public class NotInitialization {
public static void main(String[] args) {
//System.out.println(SubClass.value);
SuperClass[] superClasses = new SuperClass[10];
}
}


运行结果并没有打印出”SuperClass Init !!!”,这里并没有出发com.sun.jojo.noinitclass.SuperClass类的初始化.这里触发了另一个名为“[Lcom.sun.jojo.noinitclass.SuperClass”的类的初始化,他是虚拟机自动创建的,直接继承于java.lang.Object的子类,创建动作由字节码指令newarray触发。

3.常量在编译期间就会调入类的常量池中,本质上没有直接引用的定义变量的类,因此使用常量字段时不会触发累的初始化。

public class ConstClass {
static {
System.out.println("ConstClass Init !!!");
}
public static final int value = 123;
}

public class NotInitialization {
public static void main(String[] args) {
//System.out.println(SubClass.value);
//SuperClass[] superClasses = new SuperClass[10];
System.out.println(ConstClass.value);
}
}


结果:只打印出123 “ConstClass Init !!!”并没有打印出来。

接口的初始化和类的初始化类似,区别在于5种中的第三种:当一个子类的初始化过程中需要去报其父类也必须先初始化,但接口初始化时不要求其父接口也进行初始化,只有在用到父接口时,才去初始化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  虚拟机 java class