不要在构造函数中调用可重写的方法 这句话对吗?看了一个帖子,想了很久,还是不明白http://topic.csdn.net/u/20110626/14/dd92aaec-1c82-450d-a0a4-273d8cb6103c.html 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 《java 编程思想4》第八章 多态 有一个与上面帖子相似的例子 P163如果要调用构造器内部的一个动态绑定方法,就要用到那个方法被覆盖后的定义。然而,这个调用的效果可能相当难以预料,因为被覆盖的方法在对象被完全构造之前就会被调用。这可能会造成一些难于发现的隐藏错误。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=0Glyph() after draw()RoundGlyph. RoundGlyph(),radius=5*/Glyph.draw()方法设计为将要被覆盖,这种覆盖是在RoundGlyph中发生。但是Glyph构造器会调用这个方法,结果导致了对RoundGlyph.draw()的调用,这看起来是我们的目的。但是如果看到输出结果,我们发现当Glyph的构造器调用draw()方法时,radius不是默认初始值1,而是0。.初始化的实际过程是:1) 在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。2) 如前所述那样调用基类构造器。此时,调用被覆盖后的draw()方法(要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,此时我们会发现radius的值为0.3) 按照声明的顺序调用成员的初始化方法4) 调用导出类的构造器主体而在章节结尾处,作者这样写道:编写构造器时有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。在构造器内唯一能够安全调用的方法是基类中的final(也适用于private)方法,这些方法不能被覆盖。你可能无法总是能够遵循这条准则,但是应该朝着它努力。 这个怎么办啊? 会汇编的请进!!! 写一静态方法 在java中如何动态地声明一个对象? 内部类实例化 文件打印问题,高手求教 如何让JTree初始化的时候全部展开,并且让某个指定的叶子用不同的颜色表示出来? 还是多线程问题,帮看下吧。 一个很简单的菜鸟问题。顺序问题 JAVA插入数据库的一个中文问题!!特急,谢谢各位了 SAX解析XML 建立结点问题 netbeans如何使用图片做界面背景
如果要调用构造器内部的一个动态绑定方法,就要用到那个方法被覆盖后的定义。然而,这个调用的效果可能相当难以预料,因为被覆盖的方法在对象被完全构造之前就会被调用。这可能会造成一些难于发现的隐藏错误。
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。.
初始化的实际过程是:
1) 在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。
2) 如前所述那样调用基类构造器。此时,调用被覆盖后的draw()方法(要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,此时我们会发现radius的值为0.
3) 按照声明的顺序调用成员的初始化方法
4) 调用导出类的构造器主体而在章节结尾处,作者这样写道:编写构造器时有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。
在构造器内唯一能够安全调用的方法是基类中的final(也适用于private)方法,这些方法不能被覆盖。你可能无法总是能够遵循这条准则,但是应该朝着它努力。