Java 中的静态/实例初始值设定项块以什么顺序运行?

2022-08-31 10:08:16

假设一个项目包含多个类,每个类都有一个静态初始值设定项块。这些块以什么顺序运行?我知道在类中,这些块按照它们在代码中出现的顺序运行。我已经读到它跨类是相同的,但我写的一些示例代码不同意这一点。我用了这个代码:

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
静态 - 祖父母
静态 - 父
静态 - 子
实例 - 祖父母
构造函数 - 祖父母
实例 - 父
构造函数 - 父
实例 - 子
构造函数 - 子
END

从中得到的明显答案是,父母的区块在孩子的区块之前运行,但这可能只是一个巧合,如果两个班级不在同一层次结构中,则无济于事。

编辑:

我通过将其附加到 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");
    }
}

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


答案 1

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

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

类或接口类型 T 将在首次出现以下任一项之前立即初始化:

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

(以及几个黄鼠狼词条)


答案 2

类的静态初始值设定项在首次访问类时运行,以创建实例或访问静态方法或字段。

因此,对于多个类,这完全取决于为加载这些类而运行的代码。


推荐