作者:凯文 @开源Favorer
类初始化顺序是 JAVA 中的重要知识点,但长期以来不为人们所热议,那么下面的问题将可以帮助你快速识别自己是否已掌握相关知识。
问题:你认为下面的代码片段执行结果B的值是多少?
public class Parent {
public static int A = 1;
static {
A = 2;
}
}
public class Child extends Parent {
public static int B = A;
public static void main(String args[]) {
System.out.println(B);
}
}
如果你心中还没有明确的答案,下面我们就来一起认识一下类初始化顺序问题。
关于clinit
如果您曾经有留心过 字节码 的内容,可能你已经发现,其中出现了你未曾在JAVA文件中定义过的clinit()方法。事实上,这是 JVM 的一种工作机制,一旦你的类中有静态变量或 静态方法 ,都会在字节码中出现该方法。
关于init
init方法是对象初始化时调用的方法, 调用类或 Java.lang.reflect. Constructor 对象的 newInstance() 方法;调用任何现有对象的 clone() 方法; java.io.Object InputStream 类的 getObject() 方法反序列化等。
类初始化顺序
clinit: 在Java编译之后会在字节码文件中生成<clinit>方法,成为类构造器, 包括 静态变量 初始化和静态块的执行 。收敛到clinit,收敛顺序为(父类的先执行):
- 父类静态变量初始化
- 父类静态语句块
- 子类静态变量初始化
- 子类静态语句块
init: 在Java编译之后会在字节码文件中生成<init>方法,成为实例 构造器 。该实例构造器会将语句块,变量初始化,调用父类的构造器等操作收敛到init方法,收敛顺序:
- 父类变量初始化
- 父类语句块
- 父类构造函数
- 子类变量初始化
- 子类语句块
- 子类构造函数
clinit在类加载过程中执行,init在实例化过程中执行,clinit先于init执行。
以上就是关于类加载顺序的冷知识,相信你对本CHAT开始的问题已有了非常清晰的答案。关注小编,了解那些你可能忽略的知识。
开源Favorer为读者提供了广泛的IT认证类辅导资料,欢迎点击领取