Java构造函数内部的多态行为可能带来的问题

《Thinking in Java》

Java构造函数的初始化顺序

  1. 在所有事情发生之前,将该类以及其基类的所有对象分配的存储空间初始化为二进制的零。比如int类型会分配为0,对象会被初始化为null。

  2. 调用基类的构造方法,并且不断递归下去。也就是必须先调用最上层的基类的构造方法,直到最底层的导出类

  3. 按照声明的顺序,调用成员变量的初始化方法。一般成员变量都会声明在类的前面,在调用构造函数的主体之前,会先对这些变量初始化赋值。

  4. 调用导出类的构造方法的主体

Java构造函数的初始化顺序看起来没有什么大问题,不过在一些特殊的情况下,还是有可能会出现错误的。比如下面的类:

public class Main{

    public static void main(String[] args){
        new Child(5);
    }

}

class Parent{
    public Parent(){
        System.out.println("Build parent before");
        printValue();
        System.out.println("After parent before");
    }

    public void printValue(){
        System.out.println("Parent printValue");
    }
}

class Child extends Parent{
    private int value=1;
    public Child(int value){
        this.value=value;
    }

    public void printValue(){
        System.out.println("Child printValue: value="+value);
    }
}

输出结果

Build parent before
Child printValue: value=0
After parent before

可以看到,由于在导出类的基类的构造函数中调用了多态方法printValue(),这个方法在对象被完全初始化之前就调用了,也就是基类的构造方法调用了导出类的方法,而这个方法所使用的成员变量在导出类中可能还没有被初始化,因此会出现一些可怕的错误。比如在这个例子中,输出的是int的系统初始化值0

从上面的例子我们可以看出,由于多态机制的存在,在构造函数中使用多态方法可能会导致难以察觉的错误,因此我们要尽量避免在构造函数中调用其它方法,如果无法避免,也应该用那些在基类中属于final或者private类型的方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值