构造器调用的层次结构带来了一个困境。如果在构造器中调用了正在构造的对象的动态绑定方法,会发生什么呢?
翻译过来:class B 继承 class A, B 重写了A 中的 f(), A 在构造器中调用了 f(),现在如果初始化B,会出现什么情况呢?
// polymorphism/PolyConstructors.java
// Constructors and polymorphism
// don't produce what you might expect
class Glyph {
void draw() {
System.out.println("Glyph.draw()");
}
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int r) {
radius = r;
System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
}
@Override
void draw() {
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}
public class PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
错误输出:
Glyph() before draw()
RoundGlyph.draw(), radius = 1
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
我们需要明确一点,Java 中属性的初始化,其实是分为两步的:
- 为属性开辟内存空间,赋予初始值(0,false,null)
- 将属性初始化为用户指定的默认值
正确输出:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
解析:
-
main()方法执行,准备初始化一个RoundGlyph对象 -
初始化
RoundGlyph时,发现有父类Glyph需要先初始化 -
初始化
Glyph,默认调用无参构造器Glyph()- 输出
Glyph() before draw() - 执行
draw()- 因为是在初始化
RoundGlyph,所以需要调用RoundGlyph.draw()【或许,有大佬提供更合理的解释?】 - 执行
draw()的过程中,发现需要使用变量radius,此时,radius仅仅被分配存储空间,被赋予默认初值,还未被用户指定的初值1覆盖 - 输出结果为
"RoundGlyph.draw(), radius = 0
- 因为是在初始化
- 输出
Glyph() after draw()
- 输出
-
Glyph初始化完成,开始初始化RoundGlyph -
radius的值,初始化为 1 -
执行构造器
RoundGlyph(int r)- 覆盖
radius的值,为 5 - 输出
RoundGlyph.draw(), radius = 5
- 覆盖