“当一个类被加载时”到底是什么意思?
2022-09-02 22:18:37
据说Java中的静态块在加载该类时只运行一次。但这到底意味着什么呢?在哪一点上,JVM(Java虚拟机)装入了类?
是当调用该类中的 main 方法时吗?当 main 方法开始执行时,是否也加载了同一类的所有超类?
考虑 A 扩展 B,B 扩展 C。它们都有静态块。如果 A 有 main 方法,那么静态块的执行顺序是什么?
据说Java中的静态块在加载该类时只运行一次。但这到底意味着什么呢?在哪一点上,JVM(Java虚拟机)装入了类?
是当调用该类中的 main 方法时吗?当 main 方法开始执行时,是否也加载了同一类的所有超类?
考虑 A 扩展 B,B 扩展 C。它们都有静态块。如果 A 有 main 方法,那么静态块的执行顺序是什么?
这在 JLS 的执行部分中进行了描述。即:
类的初始化包括执行其静态初始值设定项和类中声明的静态字段的初始值设定项。接口的初始化包括为接口中声明的字段执行初始值设定项。
在初始化类之前,必须初始化其直接超类,但不需要初始化该类实现的接口。同样,接口的超接口在初始化接口之前不需要初始化。
因此,在您的示例中,“最顶层”类 () 的静态块首先运行,然后是 的 静态块,然后是 派生次数最多的静态块。C
B
有关加载类的所有步骤的详细说明,请参阅该文档。
(类在首次被主动使用时加载。
我认为以下示例将解决您的所有问题:
在初始化类之前,如果以前未初始化其超类,则会对其进行初始化。
因此,测试程序:
class Super {
static { System.out.print("Super "); }
}
class One {
static { System.out.print("One "); }
}
class Two extends Super {
static { System.out.print("Two "); }
}
class Test {
public static void main(String[] args) {
One o = null;
Two t = new Two();
System.out.println((Object)o == (Object)t);
}
}
指纹:
Super Two false
类 One 永远不会初始化,因为它未主动使用,因此永远不会链接到。类二仅在其超类 Super 初始化后才初始化。
有关更多详细信息,请访问此链接
编辑详细信息:删除了令人困惑的行。