关于继承中构造器调用多态方法的一个细节

Java的动态绑定是与C++不同的一大特点。这篇文章主要记录看Java编程思想关于继承中的多态的详细讲解部分的一些细节,并由此给出了一条编程准则。


继承中构造器的调用顺序为:首先调用所有基类的构造器(从最上层的基类开始),然后按声明顺序调用成员的初始化方法,最后调用本类的构造器(C++的构造函数调用顺序也一样)。可以用下面的代码测试:

class Meal {
    Meal() {
        System.out.println("Meal");
    }
}
class Bread {
    Bread() {
        System.out.println("Bread");
    }
}
class Milk {
    Milk() {
        System.out.println("Milk");
    }
}
class Breakfast extends Meal {
    Breakfast() {
        System.out.println("Breakfast");
    }
}
public class Sandwich extends Breakfast {
    private Bread b = new Bread();
    private Milk m = new Milk();
    public Sandwich() {
        System.out.println("Sandwich");
    }
    public static void main(String[] args) {
        new Sandwich();
    }
}
/*输出为
Meal
Breakfast
Bread
Milk
Sandwich*/

如果要调用构造器内部一个动态绑定的方法,就要用到该方法覆写后的方法,而覆写后的方法可能需要子类成功初始化后才能正常被调用。由于构造器的顺序是先调用基类的构造器,因此可能会出现预期之外的运行错误。如下面的代码:

class Graphic {
    void draw() {
        System.out.println("Graphic draw()");
    }
    Graphic() {
        System.out.println("Graphic() before draw()");
        draw();
        System.out.println("Graphic() after draw()");
    }
}
class Circle extends Graphic {
    private int radius = 1;
    Circle(int r) {
        radius = r;
        System.out.println("Circle(), radius = " + radius);
    }
    void draw() {
        System.out.println("Circle(), radius = " + radius);
    }
}
public class Test {
    public static void main(String[] args) {
        new Circle(5);
    }
}
/*输出为
Graphic() before draw()
Circle(), radius = 0
Graphic() after draw()
//前三行调用的是基类的构造器,但第二行语句draw()调用的是动态绑定的子类的覆写后的方法,而此时子类还没有初始化,因此半径输出是错误的。
Circle(), radius = 5
*/

因此前面所说的构造器的调用顺序其实是不完全的,事实上在任何调用之前,构造器会首先将分配给对象的存储空间初始化为二进制的0,再执行上述顺序。这就保证了没有初始化的任何数据都是0。如果是C++,那么在处理这种情况时会更加合理,它的输出结果为:

/*Graphic() before draw()
Graphic draw()
Graphic() after draw()
Circle(), radius = 5*/

总之,在Java中编写构造器时有一条准则:用尽可能简单的方法使对象进入正常状态。如果可以,避免使用其他方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值