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
类型的,在中]两个构造函数调用,调用的是B
的foo()
方法。这就是为什么两个输出行都以 B.foo(): bar = ...
.
开头的原因
最后,第一行打印 = null
而不是 B.bar
的原因是因为它试图在 [=12= 中打印 bar
变量的值] class before B
class甚至已经开始初始化它的字段,所以值仍然是null
。 B
的 bar
变量仅在 A
的构造函数完成其工作后才被初始化。
这就是为什么您永远不想在 class 构造函数中调用可覆盖方法的原因。它会导致像这样的意外行为,您可能会无意中读取未初始化的字段。 This thread 对此进行了更详细的解释。
为什么输出是:
> 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
类型的,在中]两个构造函数调用,调用的是B
的foo()
方法。这就是为什么两个输出行都以 B.foo(): bar = ...
.
最后,第一行打印 = null
而不是 B.bar
的原因是因为它试图在 [=12= 中打印 bar
变量的值] class before B
class甚至已经开始初始化它的字段,所以值仍然是null
。 B
的 bar
变量仅在 A
的构造函数完成其工作后才被初始化。
这就是为什么您永远不想在 class 构造函数中调用可覆盖方法的原因。它会导致像这样的意外行为,您可能会无意中读取未初始化的字段。 This thread 对此进行了更详细的解释。