请问Java中的静态/实例初始化块按照什么顺序运行?

Java中的静态/实例初始化块按照什么顺序运行?

假设一个项目包含几个类,每个类都有一个静态初始化块。这些块按什么顺序运行?我知道,在类中,这样的块是按照它们在代码中出现的顺序运行的。我读过不同的类都是一样的,但是我编写的一些示例代码不同意这一点。我使用了这个代码:

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");
    }}

得到了这个输出:

启动
静态祖父母
静态亲本
静态子
实例-祖父母
构造师-祖父母
实例-父母
构造函数-父
实例-儿童
构造函数-子
端部

显而易见的答案是,父母的街区跑在他们的孩子之前,但这可能只是一个巧合,如果两个班级不属于同一等级,那就没有帮助了。

编辑:

我修改了示例代码,将其附加到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");
    }}

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


侃侃尔雅
浏览 242回答 3
3回答

qq_笑_17

类的静态初始化程序在首次访问类时运行,可以创建实例,也可以访问静态方法或字段。因此,对于多个类,这完全取决于运行的代码导致这些类被加载。

慕标5832272

见“公约”第12.4和12.5节JLS第8版,他们详细介绍了所有这些(静态变量为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)。(还有几个脏话从句

摇曳的蔷薇

基思和克里斯的答案都很好,我只是为我的具体问题增加一些细节。静态init块按照初始化类的顺序运行。那是什么顺序?JLS 12.4.1:类或接口类型T将在第一次出现以下情况之前立即初始化:T是一个类,并创建了一个T的实例。T是一个类,调用T声明的静态方法。指定一个由T声明的静态字段。使用由T声明的静态字段,且该字段不是常量变量(§4.12.4)。T是一个顶级类,在T中执行一个按词法嵌套的断言语句(§14.10)。类和包中某些反射方法的调用还会导致类或接口初始化。在任何其他情况下都不会初始化类或接口。为了举例说明,下面是示例中正在发生的事情的演练:进入主打印“开始”尝试创建第一个需要初始化子实例的实例尝试初始化子节点会导致父级初始化尝试初始化父级会导致祖父母的初始化。在祖父母初始化开始时,运行祖父母的静态初始化块从技术上讲,Object在初始化链中获得了最后的发言权,因为它是祖父母的父级,但是它没有什么可贡献的。在祖父母的静态初始化块结束后,程序回到父程序的静态初始化块在父程序的静态初始化块结束后,程序返回到child的静态初始化块此时,初始化了child,因此它的构造函数可以继续由于IAmAClassThatIsNeverUsed从未被引用过,因此它的任何代码都不会运行,包括静态初始化程序块。本演练的其余部分与静态初始化器无关,仅为完整性而包含子构造函数隐式调用Super()(即父构造函数)父构造函数隐式调用Super()(即祖父母的构造函数)祖父母的构造函数也是这样,没有任何效果(同样,对象没有任何贡献)在祖父母的构造函数调用Super()之后,爷爷奶奶的实例初始化程序块立即出现爷爷奶奶的构造函数的其余部分运行,构造函数终止程序返回到父构造函数,在调用Super()(即祖父母的构造函数)后立即解析如前所述,父实例初始化程序完成了它的工作,它的构造函数也完成了。类似地,程序返回并完成child的构造函数此时,对象已被实例化。打印“结束”正常终止
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java