【问题标题】:Execution of Java static blocks in subclasses在子类中执行 Java 静态块
【发布时间】:2018-02-26 12:59:51
【问题描述】:

我正在为 Java 认证测试做准备,我发现了一个与 Java 静态块的执行相关的有趣问题。我花了很多时间阅读有关此主题的内容,但没有找到我想要的答案。

我知道当类加载到JVM或调用main方法时会执行静态块,但是...

package oneClassTasks;

class Parent {
    static int age;
}

class Child extends Parent {
    static {
        age = 5;
        System.out.println("child's static block");
    }
}

public class XXX {

    public static void main(String args[]) {
        System.out.println("Child age is : "+ Child.age);
    }

}

输出是:

Child age is : 0

如果我在-verbose:class 中包含详细输出,则输出为:

...
[Loaded java.security.BasicPermissionCollection from C:\Program Files\Java\jre1.8.0_161\lib\rt.jar]
[Loaded oneClassTasks.XXX from file:/D:/temp/bin/]
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jre1.8.0_161\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jre1.8.0_161\lib\rt.jar]
[Loaded java.lang.Void from C:\Program Files\Java\jre1.8.0_161\lib\rt.jar]
[Loaded oneClassTasks.Parent from file:/D:/temp/bin/]
[Loaded oneClassTasks.Child from file:/D:/temp/bin/]
Child age is : 0
[Loaded java.lang.Shutdown from C:\Program Files\Java\jre1.8.0_161\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\Program Files\Java\jre1.8.0_161\lib\rt.jar]

我们可以在这里看到 子类被加载到 JVM 中。

谁能解释一下为什么Child类的静态块没有被执行

【问题讨论】:

    标签: java static jvm execution


    【解决方案1】:

    您看到 Child 类已加载,但尚未初始化。

    访问Child.age 不会导致Child 类的初始化,因为ageParent 类的成员。因此只有Parent类被初始化,age保持0

    12.4.1. When Initialization Occurs

    一个类或接口类型 T 将在 以下任何一项的第一次出现:

    • T 是一个类,并创建了一个 T 的实例。

    • T 声明的静态方法被调用。

    • 分配了一个由 T 声明的静态字段。

    • 使用了由 T 声明的静态字段,并且该字段不是常量变量(第 4.12.4 节)

    • T 是一个顶级类(第 7.6 节),并且会执行在词法上嵌套在 T(第 8.1.3 节)中的断言语句(第 14.10 节)。

    在您的情况下,您访问了由 Parent 声明的静态字段,因此只有 Parent 被初始化。

    【讨论】:

    • 请注意,关于 assert 语句的最后一个项目符号似乎与 Java 6 到 Java 9 中的实际行为不匹配,我猜这就是它已从 Java 9 规范中删除的原因。
    • 谢谢。现在一切都说得通了我必须开始更仔细地阅读。解释一直是here。所以,它必须被加载和初始化
    【解决方案2】:

    在这种情况下,Child.age 等同于 Parent.age。 JRE会将其视为Parent.age,这就是为什么只有Parent被静态初始化,而Child的静态初始化被跳过。

    【讨论】:

      猜你喜欢
      • 2014-06-05
      • 2022-12-22
      • 1970-01-01
      • 1970-01-01
      • 2014-08-01
      • 2013-09-25
      • 1970-01-01
      相关资源
      最近更新 更多