java - 什么时候正常的 init block 在 java 中执行

标签 java

<分区>

class Bird {
    {
        System.out.print("b1 ");
    }

    public Bird() {
        System.out.print("b2 ");
    }
}

class Raptor extends Bird {
    static {
        System.out.print("r1 ");
    }

    public Raptor() {
        System.out.print("r2 ");
    }

    {
        System.out.print("r3 ");
    }
    static {
        System.out.print("r4 ");
    }
}

class Hawk extends Raptor {
    public static void main(String[] args) {
        System.out.print("pre ");
        new Hawk();
        System.out.println("hawk ");
    }
}

我正在准备 Java OCA 考试。上面的代码来 self 正在学习的书。根据答案结果应该是

r1 r4 pre b1 b2 r3 r2 hawk

虽然我希望它是

pre r1 r4 b1 b2 r3 r2 hawk

考虑到这些规则:

  1. 静态初始化 block 在类首次加载时运行
  2. 正常的 init block 在所有 super 构造函数运行后立即运行

有人可以一步一步地告诉我这是怎么发生的吗?我可以理解 r1r4 出现在所有内容之前,但为什么 pre 紧随其后?

最佳答案

当类 Hawk 被加载时,类 RaptorBird 也必须被加载,因为它们是父类(super class),它们是 Hawk 定义的一部分。加载类时,将运行静态初始化程序。 “静态”实际上只是意味着它是类的一部分而不是类的实例。

JVM 下一步要做的是开始执行 main 方法。它是静态的,因此尚未创建任何实例。这就是接下来打印“pre”的原因。

然后 main 方法创建一个 Hawk 的实例,它将调用构造函数。在进入构造函数之前,非静态初始化 block 被执行,同时字段初始化(这些类没有),在文件中按顺序执行。

在此之后它打印“hawk”并退出。


附言。在编写代码时,我避免使用初始化 block 。当所有语句都在构造函数方法中时,更容易阅读代码并在以后理解它。一个异常(exception)是构建常量集合(即 map ),因为 Java 在其他方面并不真正支持它(与文字 map /字典/对象的 Python 或 JavaScript 语法不同)。

关于java - 什么时候正常的 init block 在 java 中执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31753815/

相关文章:

Java,Junit - 捕获标准输入/输出以用于单元测试

java - 使用 JPA 从 java map 对象自动生成表的自定义列名称

java - 为什么 java 代码缓存大小在增长?

java - 按降序对数组进行排序并显示每次迭代的输出

java - 下载 Youtube 视频?

java - 如何将 JUnit 测试用例的多个输入模拟到我的程序中?

java - Maven原型(prototype):generate | Build Failure

java - 为什么在将 BST 中的节点的键与 0 进行比较时不能使用 .compareTo() ?

java - JVM 垃圾收集和内存中 Java 数据库

java - 在appender中指定多个文件