Java中的static关键字

Aam*_*mir 10 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();
    }
}
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,则会出现异常.


Ers*_*III 1

Class B不实现(也称为“隐藏”)该static test方法,因此初始执行开始于Class A(因此是 A-SIB);然后使用test中的方法A(因此称为“A-测试”)。如果您覆盖testClass B您将获得 A-SIB B-SIB B-test

  • 您无法重写静态方法。你可以隐藏它,但它是完全不同的。 (4认同)