java - Java 中的静态/实例初始化程序 block 按什么顺序运行?

标签 java static-initializer

假设一个项目包含多个类,每个类都有一个静态初始化 block 。这些 block 按什么顺序运行?我知道在一个类中,这些 block 按照它们在代码中出现的顺序运行。我读到它在各个类中都是相同的,但我编写的一些示例代码与此不同。我使用了这段代码:

package pkg;

public class LoadTest {
    public static void main(String[] args) {
        System.out.println("START");
        new Child();
        System.out.println("END");
    }
}

class Parent extends Grandparent {
    // Instance init block
    {
        System.out.println("instance - parent");
    }

    // Constructor
    public Parent() {
        System.out.println("constructor - parent");
    }

    // Static init block
    static {
        System.out.println("static - parent");
    }
}

class Grandparent {
    // Static init block
    static {
        System.out.println("static - grandparent");
    }

    // Instance init block
    {
        System.out.println("instance - grandparent");
    }

    // Constructor
    public Grandparent() {
        System.out.println("constructor - grandparent");
    }
}

class Child extends Parent {
    // Constructor
    public Child() {
        System.out.println("constructor - child");
    }

    // Static init block
    static {
        System.out.println("static - child");
    }

    // Instance init block
    {
        System.out.println("instance - child");
    }
}

并得到这个输出:

START
static - grandparent
static - parent
static - child
instance - grandparent
constructor - grandparent
instance - parent
constructor - parent
instance - child
constructor - child
END

显而易见的答案是, parent 的 block 在 child 的 block 之前运行,但这可能只是巧合,如果两个类不在同一层次结构中,则没有帮助。

编辑:

我修改了示例代码,将其附加到 LoadTest.java:

class IAmAClassThatIsNeverUsed {
    // Constructor
    public IAmAClassThatIsNeverUsed() {
        System.out.println("constructor - IAACTINU");
    }

    // Instance init block
    {
        System.out.println("instance - IAACTINU");
    }

    // Static init block
    static {
        System.out.println("static - IAACTINU");
    }
}

正如类名所暗示的那样,我从未在任何地方引用过新类。新程序产生与旧程序相同的输出。

最佳答案

请参阅 JLS version 8 的第 12.4 和 12.5 节,他们详细介绍了所有这些(12.4 为静态变量,12.5 为实例变量)。

对于静态初始化(第 12.4 节):

类或接口(interface)类型 T 将在第一次出现以下任一情况之前立即初始化:

  • T 是一个类,并且创建了 T 的实例。
  • T 是一个类,并且调用 T 声明的静态方法。
  • 分配了 T 声明的静态字段。
  • 使用了 T 声明的静态字段,并且该字段不是常量变量(第 4.12.4 节)。
  • T 是顶级类(第 7.6 节),并且执行词法嵌套在 T(第 8.1.3 节)内的断言语句(第 14.10 节)。

(以及几个狡猾的词句)

关于java - Java 中的静态/实例初始化程序 block 按什么顺序运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35089149/

相关文章:

java - 找到一个模式,这样我就可以通过不重复计算来改进排列算法

java - 模仿java中的printStackTrace()方法

java - 在JAVA中合并两个URL

java - 为什么静态初始化程序允许在 Java 中重新初始化静态变量?

java - 一个线程可以在另一个线程完成静态初始化(类加载)之前进入静态方法吗?

java - 静态和非静态初始化代码块有什么区别

java - 与使用静态初始化器作为伪入口点相比,main(...) 有什么好处?

c# - 静态类中静态字段的初始化顺序

java - 如何修复Android Studio中的网络安全配置?

java - 为什么我们已经有了 Vector 还需要同步的 ArrayList?