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();
}
}
Run Code Online (Sandbox Code Playgroud)
当我跑C级时,我想A-SIB,B-SIB并且A-test将被打印,但B-SIB输出中没有.有人可以解释一下原因吗?
JB *_*zet 13
以下是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,则会出现异常.
Class B不实现(也称为“隐藏”)该static test方法,因此初始执行开始于Class A(因此是 A-SIB);然后使用test中的方法A(因此称为“A-测试”)。如果您覆盖test,Class B您将获得 A-SIB B-SIB B-test
| 归档时间: |
|
| 查看次数: |
397 次 |
| 最近记录: |