关于Java类初始化的一些特性

在 Java中,虚拟机对于类的加载时机并未严格的约束而是根据各虚拟机的特性自行决定,但是对于初始化来说,存在几种情况使得类必须立即执行初始化操作:

    1)当使用new,putstatic,getstatic,invokestatic这4条指令时,若该类未被初始化则需立即对该类进行初始化。

    2)对类进行反射调用时,若该类未被初始化则需立即对该类进行初始化。

    3)初始化一个类时,若该类存在父类且该父类未初始化则先初始化该类的父类。

    4)虚拟机启动阶段,会初始化用户指定的需要执行的主类。

    5)当使用Java 1.7的动态语言支持时,若一个 java.lang.invoke.MethodHandle实例最后的解析结果REF_putstatic,REF_getstatic,REF_invokestatic的方法句柄,若这个方法句柄对应的类未进行初始化则需对该类进行初始化。

上述5种情况会直接初始化对应类,接下来通过示例看下几种其他会初始化的情况:

示例1:

package testReference;

public class A {
	
	static{
		System.out.println("A class init");
	}
	
	public static String a_class = "A_CLASS";

}
package testReference;

public class B extends A {
	
	static{
		System.out.println("B class init");
	}
	
	public static String b_class = "B_CLASS";

}
package testReference;

public class Test {

	public static void main(String[] args) {
		
		System.out.println(B.a_class);

	}

} 

运行结果为:


这是因为对于静态变量,只有直接定义这个变量的类才会初始化,在上面的示例总,因为a_class是在A中定义的因此实际上只有A进行了初始化。

示例2:将上述test类变换下代码如下:

package testReference;

public class Test {

	public static void main(String[] args) {
		
		System.out.println(B.b_class);

	}

}

输出结果为:


因为这里输出的是B中的静态变量,JVM首先会检测B,因为B有父类A所以首先检测A是否已初始化,因为A尚未初始化因此会先初始化A然后再初始化B最后输出b_class。

示例3:将A中静态变量用final修饰并在test类中输出A中变量如下:

package testReference;

public class A {
	
	static{
		System.out.println("A class init");
	}
	
	public static final String a_class = "A_CLASS";

}

最后输出结果为:


这是因为在类编译阶段,通过JVM常量传播优化,已将a_class的值传给了Test类的常量池中,因此实际对B.b_class的引用直接转为自身的常量池引用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值