[#0x000B] warning: 在构造器中请谨慎使用被覆写方法

  先上代码(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])

你可能感兴趣的:(jvm,ext)