在子类中执行 Java 个静态块

Execution of Java static blocks in subclasses

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

我知道当 class 加载到 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]

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

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

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

访问 Child.age 不会导致 Child class 的初始化,因为 ageParent class 的成员.因此只有Parentclass被初始化,age仍然是0.

12.4.1. When Initialization Occurs

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.

  • A static method declared by T is invoked.

  • A static field declared by T is assigned.

  • A static field declared by T is used and the field is not a constant variable (§4.12.4).

  • T is a top level class (§7.6) and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.

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

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