笔记

注意:字节码文件中初始化方法有两种,非静态资源初始化的<init>和静态资源初始化的<clinit>,类构造器方法<clinit>()不同于类的构造器,这些方法都是字节码文件中只能给JVM识别的特殊方法。

初始化其实就是执行类构造器方法的<clinit>()的过程,而且要保证执行前父类的<clinit>()方法执行完毕。这个方法由编译器收集,顺序执行所有类变量(static修饰的成员变量)显式初始化和静态代码块中语句。此时准备阶段时的那个 static int a 由默认初始化的0变成了显式初始化的3。 由于执行顺序缘故,初始化阶段类变量如果在静态代码块中又进行了更改,会覆盖类变量的显式初始化,最终值会为静态代码块中的赋值。

执行过程

  1. <clinit>()方法不需要定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句按顺序合并而来。
  2. 若该类具有父类,JVM会保证子类的<clinit>()执行前,父类的<clinit>()已经执行完毕
  3. 虚拟机必须保证一个类的<clinit>()方法在多线程下被同步加锁 jvm保证。这个特性,可以用来保证单例模式的实现。