不要在构造器中调用可覆写的步骤
不要在构造器中调用可覆写的方法
首先看一下下面的程序,猜猜会输出什么:
class Point{ Point(){ show(); } void show(){ System.out.println("Father."); } } class ColorPoint extends Point{ void show(){ System.out.println("Son."); } public static void main(String args[]){ ColorPoint point=new ColorPoint(); } }
由于,在子类的构造函数中会默认的调用父类的构造函数,但是父类的构造函数调用了被子类重载过得方法。这会导致直接调用子类覆盖后的方法。
所以输出结果:
Son.
看懂了上面的代码,再分析分析下面的代码:
class Point{ protected final int x,y; private final String name; Point(int x,int y){ this.x=x; this.y=y; name=makeName(); } protected String makeName(){ return "["+x+","+y+"]"; } public final String toString(){ return name; } } public class ColorPoint extends Point{ private final String color; public ColorPoint(int x,int y,String color) { // TODO Auto-generated constructor stub super(x, y); this.color=color; } protected String makeName(){ return super.makeName()+":"+color; } public static void main(String args[]){ System.out.println(new ColorPoint(4, 2, "purple")); } }
当在父类中调用makeName()方法时,由于该方法已经被子类重写过了。所以直接调用的是子类的makeName()方法。由于此时导致color域还没有被赋值还是null,导致name已将变成了[4,2]:null。执行到
this.color=color;时虽然color域被赋值但是已经无法改变name域的值。所以输出了:
[4,2]:null