以下是JLS关于类初始化的说法:
类的初始化包括执行其静态初始化程序和类中声明的静态字段(类变量)的初始化程序.
接口的初始化包括执行接口中声明的字段(常量)的初始化器.
在初始化类之前,必须初始化其直接超类,但不会初始化类实现的接口.同样,在初始化接口之前,不会初始化接口的超接口.
类或接口类型T将在第一次出现以下任何一个之前立即初始化:
T是一个类,并且创建了T的实例.
T是一个类,并且调用由T声明的静态方法.
分配由T声明的静态字段.
使用由T声明的静态字段,该字段不是常量变量(第4.12.4节).
T是顶级类(第7.6节),并且执行在词典内嵌套在T(第8.1.3节)内的断言语句(第14.10节).
对静态字段(第8.3.1.1节)的引用仅导致实际声明它的类或接口的初始化,即使它可能通过子类的名称,子接口或实现接口的类来引用.
在这种情况下,使用B类在C中执行的所有操作都是调用静态方法test()
.但是此方法在A中声明,而不是在B中声明.因此,JVM不初始化类B,因此不会调用其静态初始化程序块.
请注意,B类在C的字节码中引用,并由JVM加载.但它没有初始化.如果删除B.class
并尝试运行C,则会出现异常.