⑤. 主动引用(触发在初始化阶段的Clinit方法)
①. 当创建一个类的实例时,比如使用new关键字,或者通过反射、克隆、反序列化
②. 访问某个类或接口的静态变量,或者对该静态变量赋值
③. 调用类的静态方法
④. 反射(比如:Class.forName(“com.xiaozhi.Test”))
⑤. 初始化一个子类(当初始化子类时,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化)
⑥. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类
⑦. JDK7开始提供的动态语言支持
(涉及解析REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄对应的类)
⑧. 如果一个接口定义了default方法,那么直接实现或者间接实现该接口的类的初始化,该接口要在其之前被初始化
# 注意,如果把A接口中的默认方法注释,那么就只输出:子类初始化...... 输出: CompareB的初始化 子类初始化..... public class DemoB implements A{ static{ System.out.println("子类初始化......"); } public static void main(String[] args) { } } interface A{ public static final Thread t = new Thread() { { System.out.println("CompareB的初始化"); } }; default void method1(){ System.out.println("===="); } }
⑥. 被动使用
①. 除了以上的情况属于主动使用,其他的情况均属于被动使用。被动使用不会引起类的初始化。意味着没有<clinit>()的调用。
②. 调用ClassLoader类的loadClass()方法加载一个类,并不是对类的主动使用,不会导致类的初始化
③. 当访问一个静态字段时,只有真正声明这个字段的类才会被初始化。
当通过子类引用父类的静态变量,不会导致子类初始化
④. 引用常量不会触发此类或接口的初始化。因为常量在链接阶段就已经被显式赋值了
⑤. 通过数组定义类引用,不会触发此类的初始化
# 这里不会进行初始化,因为相当于parent只开辟了空间,没赋值 Parent[]parent=new Parent[10];