日期:2014-05-20  浏览次数:20690 次

关于构造器的疑惑

public class ClassB extends ClassA{

public static void main(String[] args) {
new ClassB();
}

public ClassB() {

}

public void action(){
System.out.println("重写");
}
}

class ClassA{

public ClassA() {
action();
}
public void action(){
System.out.println("父类");
}
}


为什么会调用子类重写的方法呢?明明是在父类的构造器里

------解决方案--------------------
被子类覆盖了


《java 编程思想4》第八章 多态 

如果要调用构造器内部的一个动态绑定方法,就要用到那个方法被覆盖后的定义。然而,这个调用的效果可能相当难以预料,因为被覆盖的方法在对象被完全构造之前就会被调用。这可能会造成一些难于发现的隐藏错误。

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);
   }
   void draw() {
      System.out.println("RoundGlyph.draw(),radius="+radius);
   }   
}

public class PolyConstructors {
   public static void main(String args[]) {
      new RoundGlyph(5);
   } 
}
/*
Output:
Glyph() before draw()
RoundGlyph.draw(),radius=0
Glyph() after draw()
RoundGlyph. RoundGlyph(),radius=5
*/


Glyph.draw()方法设计为将要被覆盖,这种覆盖是在RoundGlyph中发生。但是Glyph构造器会调用这个方法,结果导致了对RoundGlyph.draw()的调用,这看起来是我们的目的。但是如果看到输出结果,我们发现当Glyph的构造器调用draw()方法时,radius不是默认初始值1,而是0。.
初始化的实际过程是: