问题说明
求以下输出:
1 | public class Window { |
错误答案
1 | House() |
错误思路
从主函数出发创建一个House类对象h,构造函数会在创建对象的同时执行,找到House类的构造函数,先输出House(),因为w3是个没被声明的变量,所以先运行了Window w3 = new Window(3)
输出Window(3)然后再完成构造函数,输出Window(33),然后按照顺序完成以下输出。
正确答案
1 | Window(1) |
分析
在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。在House类中,故意把几个Window对象的定义散布到各处,以整明它们全都会在调用构造器或其他方法之前得到初始化。此外,w3在构造期内再次被初始化。
总结
其实在意识到如果构造函数先执行的话w3 = new Window(33)
这一句中的w3是一个没有被声明的变量时就觉得不太对,但还是没有找出正确的思路。后来在尝试别的情况时把这一句注释掉了,输出顺序还是不变,只是少了一句Window(33)。
2019-09-06
今天在学习多态的过程中又遇到了一个初始化顺序的问题,代码如下:
1 | class Glyph { |
错误答案:
1 | Glyph() before draw() |
错误思路:
首先调用基类构造器,考虑到新创建的对象是RoundGlyph()类的,我认为此处的draw()方法应该已经被覆盖,应该调用子类的draw方法,radius的值在子类中被初始化为1,因此得到了第二行的输出。最后再调用子类构造器的主体,输出第四行。
正确答案:
1 | Glyph() before draw() |
正确思路:除了第二行radius的值以外都对了。初始化的实际过程是:1)在其他任何事物发生之前,将分配给对象的存储空间初始化为二进制的0。2)如前所述那样调用基类构造器。此时,调用被覆盖后的draw()方法(需要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,我们此时会发现radius的值为0。3)按照声明的顺序调用成员的初始化方法。4)调用导出类的构造器主体。