所以我有以下 3 个类:
具有 1 个字段和 1 个调用方法的构造函数的类“A”:
public class A {
String bar = "A.bar";
A() {
foo();
}
public void foo() {
System.out.println("A.foo(): bar = " + bar);
}
}
第二个类“B”继承自 A,具有 1 个字段和 1 个调用方法的构造函数:
public class B extends A {
String bar = "B.bar";
B() {
foo();
}
public void foo() {
System.out.println("B.foo(): bar = " + bar);
}
}
包含主要方法的第三个类“C”:
public class C {
public static void main(String[] args) {
A a = new B();
System.out.println("a.bar = " + a.bar);
a.foo();
}
}
输出是:
B.foo(): bar = null
B.foo(): bar = B.bar
a.bar = A.bar
我在 Debug模式下跟踪程序,但我仍然不太清楚输出结果。如果能详细解释发生的过程及其背后的原则,我将不胜感激。 非常感谢。
编辑:就像人们指出的那样,我确实忘记了输出的最后一行:
B.foo(): bar = B.bar
最佳答案
首先调用 B 类的构造函数。但是,如果您扩展一个类并且没有显式调用基类的构造函数(或派生类的其他构造函数),那么每个默认构造函数的第一行都是(隐藏)调用 super()
,即基类的构造函数(在本例中为 A)。因此,我们正在处理 A 的构造函数,它调用方法 foo()
。由于此方法在类 B 中被重写,因此调用重写的实现。现在事情变得有趣了 - B 的构造函数仍然没有完成,所以 bar
的值仍然没有设置,因此输出:
B.foo(): bar = null
我们现在回到 B 的构造器,它输出
B.foo(): bar = B.bar
最后输出
a.bar = A.bar
是由于variable shadowing .
关于java构造函数行为继承和静态/动态绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31075040/