关于构造器的疑惑
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("父类");
}
}
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
*/
1)在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。
2)如前所述那样调用基类构造器。此时,调用被覆盖后的draw()方法(要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,此时我们会发现radius的值为0.
3)按照声明的顺序调用成员的初始化方法
4)调用导出类的构造器主体
而在章节结尾处,作者这样写道:编写构造器时有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。
在构造器内唯一能够安全调用的方法是基类中的final(也适用于private)方法,这些方法不能被覆盖。你可能无法总是能够遵循这条准则,但是应该朝着它努力。
[解决办法]
简单的分成两个部分:
1,虽然子类ClassB的构造方法是空的,但是实例化子类ClassB时会调用父类的构造函数ClassA,所以test()犯非法会被调用。
2,由于实例化的是ClassB类,并且ClassB类覆盖了父类的test方法,所以当该实例调用test方法时,被调用的是子类的test方法。