【问题标题】:Why is sub class' static code getting executed?为什么子类的静态代码会被执行?
【发布时间】:2016-05-11 02:28:48
【问题描述】:

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

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 类做任何这些。那为什么我会看到“子”,即子类的静态块输出?

【问题讨论】:

  • 执行main 方法(嵌套在Sub 类中)是一个静态引用。 :)
  • @KonstantinYovkov 我想过这一点,但即便如此,“sub”也应该首先出现。现在,从 Bathsheba 的回答中消除了这个疑问,因为静态块按超类和子类的顺序执行。谢谢。
  • @anil 不是第一个,Sub 类仍然依赖于Super 类,因此先执行。

标签: java constructor static static-methods


【解决方案1】:

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

您的代码没有,但为了让main 运行,必须加载Sub。所以它的静态初始化器运行。

例如,我假设你是这样运行的:

java Sub

java 工具必须加载Sub 才能调用Sub.main。那是导致静态初始化程序运行的静态引用(实际上是访问)。 (如果在 IDE 中运行,IDE 会执行java 工具部分,但结果是一样的。)

这就是发生的事情:

  1. java 触发 Sub 的加载

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

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

    super
    sub
    
  4. java 工具调用main

  5. main 中的代码调用new SuperClass

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

    2
    
  7. main 中的代码调用SuperClass.b

    2
    

作为Holger 有帮助的points out,这在§5.5 - Initialization 和相关的§5.2 - Java Virtual Machine Startup 中的JVM 规范中涵盖:

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

类或接口 C 只能作为以下结果进行初始化:

  • ...

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      在调用main时,所有的静态初始化器都会被调用,首先是在超类中,然后是子类中。

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

      【讨论】:

        【解决方案4】:

        加载类时运行静态块。通常那是因为您调用了构造函数或静态成员。在这种情况下,这是因为您执行了 main 方法(静态成员)。

        旁注:

        1. 另一个极端情况是调用 Class.forName(className) 来加载一个类。
        2. 您可能还会注意到,基类是在子类之前加载的。

        【讨论】:

          猜你喜欢
          • 2014-08-01
          • 2011-11-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-13
          • 2016-05-16
          • 1970-01-01
          相关资源
          最近更新 更多