[#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])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值