【深入理解Java虚拟机】笔记5:Java类加载中被动引用例子

版权声明:本文为个人学习总结,欢迎转载,转载时请附加原文链接 https://blog.csdn.net/cockroach02/article/details/88378146
一、通过子类引用父类的静态字段,不会导致子类初始化
package com.example.jvm;

public class SuperClass {

	static {
		System.out.println("superClass init!");
	}
	
	public static int value = 123;
}
package com.example.jvm;

public class SubClass extends SuperClass {

	static {
		System.out.print("subclass init!");
	}
}
package com.example.jvm;

public class NotInitApp {

	public static void main(String[] args) {
		System.out.print(SubClass.value);
	}
}

输出如下

superClass init!
123

解释说明:对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。


二、通过数组定义来引用类,不会触发此类的初始化
package com.example.jvm;

public class NotInitApp {

	public static void main(String[] args) {
		SuperClass[] arr = new SuperClass[10];
		System.out.println(arr);
	}
}

输出入下

[Lcom.example.jvm.SuperClass;@15db9742

解释说明:运行之后并没有输出"SuperClass init!",说明并没有触发类SuperClass的初始化阶段,但是触发了另外一个名为“[Lcom.example.jvm.SuperClass”类的初始化,对于用户代码而言,这并不是一个合法的类名称,它是一个由虚拟机自动生成的,直接继承于java.lang.Object的子类,创建动作由newarray触发。


三、使用static final修饰的字段被其他类引用的时候不会触发这个类的初始化
package com.example.jvm;

public class ConstantClass {
	
	static {
		System.out.println("ConstantClass init!");
	}
	
	public static final int value = 10;
}
package com.example.jvm;

public class NotInitApp {

	public static void main(String[] args) {
		System.out.println(ConstantClass.value);
	}
}

输出如下:

10

解释说明:使用static final修饰的常量在编译的时候通过“常量传播优化”已经将对应值写入到NotInitApp常量区了,请看我们使用jd-gui查看对应编译代码已经被修改为10了.

package com.example.jvm;

import java.io.PrintStream;

public class NotInitApp
{
  public static void main(String[] args)
  {
    System.out.println(10);
  }
}

猜你喜欢

转载自blog.csdn.net/cockroach02/article/details/88378146
今日推荐