1. <clinit>()
方法
Java 类加载的初始化过程中,编译器按语句在源文件中出现的顺序,依次自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并产生 <clinit>() 方法。 如果类中没有静态语句和静态代码块,那可以不生成
()` 方法。
并且 <clinit>()
不需要显式调用父类(接口除外,接口不需要调用父接口的初始化方法,只有使用到父接口中的静态变量时才需要调用)的初始化方法 <clinit>()
,虚拟机会保证在子类的 <clinit>()
方法执行之前,父类的 <clinit>()
方法已经执行完毕。
2. <init>()
方法
对象构造时用以初始化对象的,构造器以及非静态初始化块中的代码。
直接通过代码了解两者执行顺序上的区别:
1 | public class Test { |
输出信息如下:
1 | Copystatic开始 |
虚拟机首先执行的是类加载初始化过程中的 <clinit>()
方法,也就是静态变量赋值以及静态代码块中的代码,如果 <clinit>()
方法中触发了对象的初始化,也就是 <init>()
方法,那么会进入执行 <init>()
方法,执行 <init>()
方法完成之后,再回来继续执行 <clinit>()
方法。
上面代码中,先执行 static 代码块,此时调用了构造器,构造器中对类变量 x 和 y 进行加 1 ,之后继续完 static 代码块,接着执行下面的 public static int x = 6;
来重新给类变量 x 赋值为 6,因此,最后输出的是 x=6, y=1。