在子类中执行 Java 静态块

Posted

技术标签:

【中文标题】在子类中执行 Java 静态块【英文标题】:Execution of Java static blocks in subclasses 【发布时间】: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类的静态块没有被执行

【问题讨论】:

【参考方案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的静态初始化被跳过。

【讨论】:

以上是关于在子类中执行 Java 静态块的主要内容,如果未能解决你的问题,请参考以下文章

Java子父类间静态代码块非静态代码块构造方法的执行顺序

一文详解:Java中父子类静态块构造块构造方法成员变量之间的初始化先后顺序与执行先后顺序

java对象的初始化过程和创建对象的几种方式

Java中的Static静态代码块以及各代码块之间的执行顺序

Java中的Static静态代码块以及各代码块之间的执行顺序

Java中的Static静态代码块以及各代码块之间的执行顺序