static keyword in Java


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-SIBB-SIBA-test会被打印出来,但输出中没有B-SIB。有人能解释一下原因吗?

以下是JLS关于类初始化的说明:

类的初始化包括执行其静态初始化器和类中声明的静态字段(类变量)的初始化器。

接口的初始化包括执行接口中声明的字段(常量)的初始化程序。

在初始化类之前,必须初始化其直接超类,但该类实现的接口不会初始化。类似地,在初始化接口之前,不会初始化接口的超接口。

类或接口类型T将在以下任何一项首次出现之前立即初始化:

  • T是一个类,并且创建了T的一个实例
  • T是一个类,并且调用由T声明的静态方法
  • 指定了一个由T声明的静态字段
  • 使用由T声明的静态字段,并且该字段不是常量变量(§4.12.4)
  • T是顶级类(§7.6),执行嵌套在T(§8.1.3)中的断言语句(§14.10)

对静态字段(§8.3.1.1)的引用只会导致初始化实际声明它的类或接口,即使它可能通过子类、子接口或实现接口的类的名称来引用。

在这种情况下,在C中使用类B所做的就是调用静态方法test()。但是这个方法是在A中声明的,而不是在B中声明的。因此,JVM不会初始化类B,因此也不会调用其静态初始化器块。

注意,类B在C的字节码中被引用,并由JVM加载。但它没有初始化。如果删除B.class并尝试运行C,则会出现异常。

Class B不实现(也称为"隐藏")static test方法,因此初始执行在Class A内开始(因此为A-SIB);然后用CCD_ 11中的CCD_。如果您在Class B中覆盖test,您将获得A-SIB B-SIB B-test

最新更新