为什么子类的静态代码被执行?

AV9*_*V94 24 java static constructor static-methods

我编写了以下代码并为超类创建了对象.

class SuperClass{
    static int a=2;
    static int b(){
        return 2;
    }
    int c(){
        return 2;
    }

    SuperClass(){
        System.out.println("Super");
    }
    static {
        System.out.println("super");
    }
}

public class Sub extends SuperClass{
    Sub(){
    System.out.println("Sub");
    }
    static {
        System.out.println("sub");
    } 
    static int b(){
        return 3;
    }
    int c(){
        return 3;
    }
    public static void main(String ax[]){
        SuperClass f =new SuperClass();
        System.out.println(f.c());
        System.out.print(SuperClass.b());
    }   
}
Run Code Online (Sandbox Code Playgroud)

当我检查输出时,它如下:

super
sub
Super
2
2
Run Code Online (Sandbox Code Playgroud)

我知道只有在初始化类的对象或进行任何静态引用时才执行静态块.但在这里,我没有将这些中的任何一个发给Sub类.那为什么我看到"sub"即子类'静态块输出?

T.J*_*der 37

我知道只有在初始化类的对象或进行任何静态引用时才执行静态块.但在这里,我没有将这些中的任何一个发给Sub类.

您的代码没有,但为了main运行Sub它,必须加载.因此运行静态初始化程序.

例如,我假设你像这样运行它:

java Sub
Run Code Online (Sandbox Code Playgroud)

java工具必须加载Sub才能调用Sub.main.这是静态引用(访问,真的)导致静态初始化程序运行.(如果在IDE中运行它,IDE将执行java工具部分,但结果是相同的.)

所以这是发生的事情:

  1. java 触发负载 Sub

  2. JVM必须加载SuperClass才能加载Sub

  3. 所以我们看到他们的静态初始化器按顺序运行(SuperClass然后Sub):

    super
    sub
    
    Run Code Online (Sandbox Code Playgroud)
  4. java 工具电话 main

  5. main来电代码new SuperClass:

    Super
    
    Run Code Online (Sandbox Code Playgroud)
  6. main电话中的代码f.c()

    2
    
    Run Code Online (Sandbox Code Playgroud)
  7. main来电代码SuperClass.b:

    2
    
    Run Code Online (Sandbox Code Playgroud)

作为霍尔格有益指出,这是由JVM规范的覆盖初始化- §5.5以及相关的第5.2节- Java虚拟机启动:

类或接口的初始化包括执行其类或接口初始化方法(第2.9节).

只有以下结果才能初始化类或接口C:

  • ...

  • 如果C是一个类,则初始化其子类之一.

  • 如果C是一个类,则将其指定为Java Virtual Machine启动时的初始类(第5.2节).

倒数第二个要点涵盖SuperClass,最后一个要点涵盖Sub.


Ted*_*opp 12

因为您的main()方法是其成员Sub,所以需要加载该类以供您的程序运行.


Bat*_*eba 9

在调用中main,所有静态初始化程序都被调用,首先在超类中调用,然后是子类.

这解释了您观察到的输出.