Java 的继承构造函数是如何工作的?

How does Java's inheritance constructor work?

为什么输出是:

> B.foo(): bar = null 
> B.foo(): bar = B.bar 
>a.bar = A.bar 
>B.foo(): bar =B.bar

但不是:

> B.foo(): bar = null 
> A.foo(): bar = A.bar 
>a.bar = A.bar 
>B.foo(): bar =B.bar

1) B 扩展了 A 那么它不应该调用 A 的 class 吗? 2) 为什么通过 a.bar class 调用 A 而不是 B ? 3)你能解释一下输出吗? 代码:

public class A {
    String bar= "A.bar";
    A() { foo(); }
    public void foo() {
        System.out.println("A.foo(): bar = "+ bar);
    }
}
public class B extends A {
    String bar= "B.bar";
    B() { foo(); }
    public void foo() {
        System.out.println("B.foo(): bar = "+ bar);
    }
}
public class C {
    public static void main(String[] args) {
        A a= newB();
        System.out.println("a.bar = "+ a.bar);
        a.foo();
    }
}

实例化具有继承的 class 时,首先调用父级的构造函数。

所以在这种情况下,首先调用 A 的构造函数。第二个调用 B 的构造函数。

B.foo(): bar = null  // output from B.foo() invoked from A's constructor
B.foo(): bar = B.bar // output from B.foo() invoked from B's constructor

在这两种情况下,构造函数都会调用 foo()。不管class中都定义了foo(),因为foo()的调用是多态的,并且创建的实例是B类型的,在中]两个构造函数调用,调用的是Bfoo()方法。这就是为什么两个输出行都以 B.foo(): bar = ....

开头的原因

最后,第一行打印 = null 而不是 B.bar 的原因是因为它试图在 [=12= 中打印 bar 变量的值] class before B class甚至已经开始初始化它的字段,所以值仍然是nullBbar 变量仅在 A 的构造函数完成其工作后才被初始化。

这就是为什么您永远不想在 class 构造函数中调用可覆盖方法的原因。它会导致像这样的意外行为,您可能会无意中读取未初始化的字段。 This thread 对此进行了更详细的解释。