首先编译下列代码:
package text;
class Glyph{
void draw(){
System.out.println("Glyph.drow()");
}
Glyph(){
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() before draw()");
}
}
class RoundGlyph extends Glyph{
private int radius=1;
public RoundGlyph(int r) {
radius=r;
System.out.println("RoundGlyph.RoundGlyph(),radius ="+radius);
}
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() before draw()
RoundGlyph.RoundGlyph(),radius =5
但是实际运行的结果是这样的
Glyph() before draw()
RoundGlyph.draw(),radius=0
Glyph() before draw()
RoundGlyph.RoundGlyph(),radius =5
分析影响
如果真的是在频幕上画画的话,本来是画一个半径为1的圆却只是一个点(或什么都看不到)。
出现原因
因为RoundGlyph.draw()方法在RoundGlyph被完全构造之前就被调用了。
在一般方法(除了final或private修饰的方法)内部,动态绑定的调用是在运行时才决定的,因为对象无法知道他是属于方法所在的那个类,还是属于那个类的导出类。
在任何构造器内部,整个对象可能只是部分形成——我们只知道基类对象已经进行初始化。如果构造器只是只是在构建对象过程中的一个步骤,并且该对象所属的类是从这个构造器所属的类导出的,那么导出部分在当前构造器正在被调用的时刻仍旧是没有被初始化的。然而,一个动态绑定的方法调用却会向外深入到继承层次结构内部,它可能调用导出类的方法。 如果我们在构造器内部这样做,那么就可能会调用某个方法(其操作的成员没有被初始化的方法)——这肯定会招致灾难。