为什么会输出下面的结果呢? class 字段是否在构造函数之前未初始化?

Why the following result is the output? Are class fields don't get initalized before the constructor?

我想明白为什么会出现下面代码的结果:

public class Base {
    private int member1 = 1;
    private int member2 = 2;

    public Base() {
        System.out.println("base ctor");
        print();
    }

    public void print() {
        System.out.println(member1 + "" + member2);
    }
}

class Derived extends Base {
    private int member3 = 3;
    private int member4 = 4;

    public Derived() {
        System.out.println("derived ctor");
        print();
    }

    public void print() {
        System.out.println(member3 + "" + member4);
    }
}

class Test{
    public static void main(String[] args) {
        Derived d = new Derived();
    }
}

是:

base ctor
00
derived ctor
34

super 的构造函数调用 print() - 打印 member 1 , member 2 我认为 member1 和 member2 已经初始化,因为我认为我知道,当我们创建一个对象时,事物的顺序是 静态字段和块先行(如果它是 class 的第一个加载) 然后实例事物(如字段和成员)按顺序进行,这意味着代码顺序在前面。

此处 - 字段位于构造函数之前,这意味着它应该 运行 并且在到达打印之前已经初始化了 member1 和 member2。

为什么打印 0 0

它是打印到 Base 还是打印到 Derived?因为它是从 Base 的构造函数调用的,所以我不明白。

谢谢。

您在 Derived 中调用了 print 方法两次 - 一次在 Base 构造函数中,一次在 Derived 构造函数中。那是因为 Derived.print() 覆盖了 Base.print().

所以这个期望:

super's constructor calls print() - which prints member 1 , member 2

... 不正确。它在 Derived 中调用 print() 实现,打印 member3member4。那些还没有初始化。

执行顺序为:

  • 基础 class 字段初始值设定项
  • 基础class构造函数体
  • 派生的 class 字段初始值设定项
  • 派生class构造函数体

如果您只是将两个 print 方法更改为 print1print2(并适当更改调用代码),那么它会打印:

base ctor
12
derived ctor
34

...如您所料。