Java构造时成员初始化的陷阱计算机等级考试
文章作者 100test 发表时间 2010:01:01 12:14:29
来源 100Test.Com百考试题网
让我们先来看两个类:Base和Derived类。注意其中的whenAmISet成员变量,和方法preProcess()
1. public class Base
2. {
3. Base() {
4. preProcess().
5. }
6.
7. void preProcess() {}
8. }
01. public class Derived extends Base
02. {
03. public String whenAmISet = "set when declared" .
04.
05. @Override void preProcess()
06. {
07. whenAmISet = "set in preProcess()" .
08. }
09. }
如果我们构造一个子类实例,那么,whenAmISet 的值会是什么呢?
1. public class Main
2. {
3. public static void main(String[] args)
4. {
5. Derived d = new Derived().
6. System.out.println( d.whenAmISet ).
7. }
8. }
再续继往下阅读之前,请先给自己一些时间想一下上面的这段程序的输出是什么?是的,这看起来的确相当简单,甚至不需要编译和运行上面的代码,我们也应该知道其答案,那么,你觉得你知道答案吗?你确定你的答案正确吗?
很多人都会觉得那段程序的输出应该是“set in preProcess()”,这是因为当子类Derived 的构造函数被调用时,其会隐晦地调用其基类Base的构造函数(通过super()函数),于是基类Base的构造函数会调用preProcess() 函数,因为这个类的实例是Derived的,而且在子类Derived中对这个函数使用了override关键字,所以,实际上调用到的是:Derived.preProcess(),而这个方法设置了whenAmISet 成员变量的值为:“set in preProcess()”。
当然,上面的结论是错误的。如果你编译并运行这个程序,你会发现,程序实际输出的是“set when declared ”。怎么为这样呢?难道是基类Base 的preProcess() 方法被调用啦?也不是!你可以在基类的preProcess中输出点什么看看,