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

2022-09-01 19:58:18

我已经编写了以下代码,并为超类创建了对象。

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());
    }   
}

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

super
sub
Super
2
2

我知道静态块仅在初始化类的对象或进行任何静态引用时才执行。但是在这里,我没有对Sub类进行任何这些,那么为什么我看到“sub”即sub类的静态块输出呢?


答案 1

我知道静态块仅在初始化类的对象或进行任何静态引用时才执行。但是在这里,我没有把这些都做成子类。

您的代码不会,但为了运行它,必须加载。因此,它的静态初始值设定项即为运行。mainSub

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

java Sub

该工具必须加载才能调用 。这是导致静态初始值设定项运行的静态引用(访问)。(如果在 IDE 中运行它,IDE 将执行工具部分,但结果是相同的。javaSubSub.mainjava

所以事情是这样的:

  1. java触发负载Sub

  2. JVM 必须加载才能加载SuperClassSub

  3. 因此,我们看到它们的静态初始值设定项按顺序运行(,然后):SuperClassSub

    super
    sub
    
  4. java工具调用main

  5. 调用中的代码 :mainnew SuperClass

    Super
    
  6. 调用中的代码mainf.c()

    2
    
  7. 调用中的代码 :mainSuperClass.b

    2
    

正如 Holger 有用地指出的那样这在 §5.5 - 初始化和相关的 §5.2 - Java 虚拟机启动中的 JVM 规范中有所涉及:

类或接口的初始化包括执行其类或接口初始化方法 (§2.9)。

类或接口 C 只能由于以下原因而初始化:

  • ...

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

  • 如果 C 是一个类,则在 Java 虚拟机启动时将其指定为初始类 (§5.2)。

倒数第二个项目符号点覆盖 ,最后一个项目符号点覆盖 。SuperClassSub


答案 2

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


推荐