当初始化不正确时

ZDNet软件频道 时间:2003-12-22 作者:ZDNet China |  我要评论(10)
本文关键词:javatips java
不要在构造方法中调用可重载的方法。你不知道重载类在那个重载方法会做些什么。在这种情况下,不但会出现很多错误,而且由这类程序产生的Bug很微妙,很难调试出来。
本文译自Builder.com,未经许可请勿转载

下面代码的输出是什么?

importjava.util.ArrayList;

public class InitializationTip {

public static void main(String args[ ]) {

new B();

}

publicInitializationTip() {

; foo();

}

protected void foo() {

// do some init work here

}

}

class B extends InitializationTip {

privateArrayList list = new ArrayList();

public B() {

foo();

}

; protected void foo() {

; System.out.println(list);

}

}

正确答案是null,而且其解释还违反常规。是这样的,当B的实例创建时,它的构造方法被调用,然后其父类的无参数的构造方法也被调用。规则是如果一个特定的父类的构造方法没有在子类的构造方法中被调用,那么编译器会插入一个父类的默认的构造方法。你可以通过查看反编译的字节码中看到这一情况。

Method B()

0 aload_0

1 invokespecial #1 <Method InitializationTip()>

4 aload_0

5 new #2 <Class java.util.ArrayList>

8 dup

9 invokespecial #3 <Method java.util.ArrayList()>

12 putfield #4 <Field java.util.ArrayList list>

15 aload_0

16 invokevirtual #5 <Method void foo()>

19 return

在B的构造方法的第一行会发出对一个InitializationTip的构造方法的调用。这个调用在对list赋值之前发生。在InitializationTip的构造方法调用一个保护成员函数foo()时会出现问题。由于foo()是protected类型的,因此它能够被子类B重载,事实上也被B重载。因为B中的重载方法foo()访问实例变量list,而list已经由构造方法赋值,所以结果输出是null。在程序执行退出了父类的构造方法之后,list会被赋值,foo()被B的构造方法调用,然后所有的如预期的发生。

教训是什么?不要在构造方法中调用可重载的方法。你不知道重载类在那个重载方法会做些什么。在这种情况下,不但会出现很多错误,而且由这类程序产生的Bug很微妙,很难调试出来。

遵守这个规则,在在构造方法中调用可重载方法可以节省很多时间和精力。



责任编辑:李宁

欢迎评论投稿

百度大联盟认证黄金会员Copyright© 1997- CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号 京ICP备09041801号-159
京公网安备:1101082134