如果在父类构造方法中调用了可被重写的方法,则可能会出现意想不到的结果。
我们来看个例子,下面是基类代码:
public class Base{
public Base(){
test();
}
public void test(){
}
}
构造方法调用了test()方法。这是子类代码:
public class Child extends Base {
private int a = 123;
public Child() {
}
@Override
public void test() {
System.out.println(a);
}
}
子类有一个实例变量a, 初始赋值为123, 重写了test()函数, 输出a的值. 下面是使用代码:
public static void main(String[] args) {
Child c = new Child();
c.test();
}
输出结果是:
0
123
第一次输出为0, 第二次输出为123. 第一行为什么是0呢? 第一次输出是在new过程中输出的, 在new过程中, 首先是初始化父类, 父类构造方法调用test()方法, test()方法被子类重写了, 就会调用子类的test()方法, 子类方法访问子类实例变量a, 而这个时候子类的实例变量的赋值语句和构造方法还没有执行, 所以输出的是其默认值0.
像这样, 在父类构造方法中调用可被子类重写的方法, 是一种不好的实践, 容易引起混淆, 应该只调用 private的方法.
参考资料
Java编程的逻辑, 马俊昌 著