对于以下代码,结果是
我在B,值是0
我在B,值是44
22
public class Test {
public static void main(String[] args) {
P b = new B();
System.out.println(b.a);
}
static class P {
public int a = 11;
public P() {
a = 22;
diplay();
}
public void diplay() {
System.out.println("I am in P, value is " + a);
}
}
static class B extends P {
int a = 33;
public B() {
a = 44;
diplay();
}
public void diplay() {
System.out.println("I am in B, value is " + a);
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先,为什么构造函数被调用两次?
为什么b.a价值22?
最后,为什么第一个a价值0呢?
每当您不提供对超类构造函数的显式调用时,Java编译器会为您插入对默认超类构造函数的隐式调用(无参数).这就像你的B构造函数真的:
public B() {
super();
a = 44;
diplay();
}
Run Code Online (Sandbox Code Playgroud)
对超类构造函数的调用调用P构造函数,该构造函数调用diplay.对象是真的B,所以用多态性,B的diplay方法被调用.
此时,您已泄露了子类实例,因为它尚未完全构建. 正因为如此,B的变量a,隐藏P的变量a,尚未初始化还,所以它还是有它的默认值,0.
然后超类P构造函数完成,构造函数的其余部分B运行,也调用diplay.此调用将查看初始化44值.
构造函数不会被调用两次; 子类构造函数B隐式调用超类构造函数P,两个构造函数都调用diplay.
返回main,您引用该字段a,但引用是在类型的变量上P.没有字段多态,因此即使对象是B在运行时,也会检索P's 的值a,并将其初始化为22.
这段代码说明了为什么它通常不是一个好主意
this在构造函数完成之前泄漏对象实例,和| 归档时间: |
|
| 查看次数: |
91 次 |
| 最近记录: |