class A {
static {
System.out.println("A-SIB");
}
static void test(){
System.out.println("A-test");
}
}
class B extends A {
static {
System.out.println("B-SIB");
}
}
class C {
public static void main(String args []){
B.test();
}
}
当我跑C级时,我认为会打印A-SIB
,B-SIB
和A-test
,但输出中没有B-SIB
。有人能解释一下原因吗?
答案 0 :(得分:13)
以下是the 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,则会出现异常。
答案 1 :(得分:1)
Class B
未实现(也称为“隐藏”)static test
方法,因此初始执行在Class A
内开始(因此为A-SIB);然后使用test
中的A
方法(因此为“A-test”)。如果您覆盖test
中的Class B
,您将获得A-SIB B-SIB B-test