Java中的static关键字

时间:2014-03-04 17:38:46

标签: 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。有人能解释一下原因吗?

2 个答案:

答案 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