当扩展类时,初始化块会如何表现?

4
我有以下代码:
public class Demo{
    public static void main(String[] args) {
        new B();
    }
}

class A {
    static {
        System.out.println("A static initializer block");
    }
    static void methodOfA() {
        System.out.println("A static method");
    }
    {
        System.out.println("A non-static initializer block");
    }
    public A() {
        System.out.println("A constructor");
    }
    public A(String a) {
        System.out.println(a);
    }
}

class B extends A {
    static {
        System.out.println("B static initializer block");
    }
    static void methodOfB() {
        System.out.println("B static method");
    }
    {
        System.out.println("B non-static initializer block");
    }
    public B() {
        super("test");
        System.out.println("B constructor");
    }
}


我得到的输出是:
A 静态初始化块 B 静态初始化块 A 非静态初始化块 测试 B 非静态初始化块 B 构造函数
但我希望它是:
A 静态初始化块 B 静态初始化块 A 非静态初始化块 B 非静态初始化块 测试 B 构造函数
因为据我所知,初始化块在构造函数之前加载。
我已经在 Google 和 Stackoverflow 上浏览了答案,但没有成功。
任何澄清都将不胜感激!

1
这个回答解决了你的问题吗?继承中静态块的行为 - andreoss
由于 A 必须在 B 之前完全初始化,因此可以合理地假设 A 构造函数在 B 的初始化程序之前被调用。 - Smutje
@andreoss 谢谢,但不幸的是这并没有回答我的问题,因为那个问题具体涉及静态初始化块的工作原理。还是感谢您的建议! - koenek
2个回答

3
超类的构造函数在子类的构造函数之前执行,非静态初始化程序在构造函数之前立即执行。因此,在您的输出中,“test”出现在“B非静态初始化块”之前。

2

静态初始化块只在JVM初始化类时执行一次,而实例初始化块每次创建类的实例时都会执行。 实例初始化块在构造函数的代码之前执行,但在调用父类构造函数(即在super()调用之后)执行。

Java编译器将实例初始化块代码复制到每个构造函数中。 实例初始化块代码放置在super()调用之后。 因此,以下代码:

{
    System.out.println("B non-static initializer block");
}

public B() {
    super("test");
    System.out.println("B constructor");
}

将被转换为:
public B() {
    super("test");
    System.out.println("B non-static initializer block");
    System.out.println("B constructor");
}

这就解释了为什么在执行B类的实例初始化块之前,控制台会先输出test

在JVM级别上,构造函数中没有任何内容被复制。此外,在构造函数之前执行实例块;此外,即使是静态绑定(在代码中初始化)的实例变量也会在构造函数体之前执行。 - Giorgi Tsiklauri
@GiorgiTsiklauri Java编译器会将初始化块复制到每个构造函数中。因此,可以使用这种方法在多个构造函数之间共享代码块 - 这段引用来自java文档 - Yousaf
@GiorgiTsiklauri 此外,实例块在构造函数之前执行;我认为这就是我在答案中所说的。实例初始化块中的代码在构造函数中的代码之前执行。唯一的例外是对super()的调用,在实例初始化块之前执行。 - Yousaf
那看起来是对的。我不小心按相反的顺序阅读了你的代码。 - Giorgi Tsiklauri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接