先上代码(adapted from Chapter 8, Thinking in Java, Fourth Edition):
class Glyph
{
void draw()
{
System.out.println("Glyph.draw()");
}
Glyph()
{
System.out.println("Glyph constructor");
draw();
}
}
class RoundGlyph extends Glyph
{
private int radius = 1;
RoundGlyph(int r)
{
System.out.println("before assignment in constructor, radius = " + radius);
radius = r;
System.out.println("RoundGlyph constructor, 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 constructor
RoundGlyph.draw(), radius = 0
before assignment in constructor, radius = 1
RoundGlyph constructor, radius = 5
*/
根据[#0x0008],调用RoundGlyph的构造器时,会先调用Glyph的构造器。Glyph的构造器里调用了一个被覆写方法draw()。这里我们惊奇地发现:虽然RoundGlyph对象还没有创建完毕,但Glyph的构造器却实际调用了RoundGlyph的draw()方法(覆写方法),而且radius == 0(参JVM-Spec $2.17.6 Creation of New Class Instances 最后一段:
If methods are invoked that are overridden in subclasses in the object being initialized, then these overriding methods are used, even before the new object is completely created.)。
由此,我们可以对[#0x0008]做一些补充,即在调用ext class的constructor时,会有如下的过程:
->将分配给该ext class object的内存空间全部初始化为0x00(即用0x00填满该段内存空间);
->调用base class的constructor。如果base class的constructor有使用被覆写方法的话,则实际调用ext class中的覆写方法。由于上一个步骤的原因,此时ext class中各field均为0;
->base class的constructor调用完毕后后,开始初始化(包括默认初始化)ext class的member;
->调用ext class的constructor。
(2009年09月04日归纳:[#0x0023])