构造器内部的多态方法的行为

[size=medium][color=darkblue]首先明确一点:Java中除了static方法和final方法(private方法属于final方法)之外,其他所有的方法都是动态绑定的。[/color][/size]

设想这样一个场景:在父类的构造器中调用一个动态绑定方法(假设叫做A),其子类重写了A方法,然后生成子类对象(目的是调用构造器),会发生什么?来看下面一个例子:
public class Test{

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

class A{
void draw(){
System.out.println("A.draw()");
}
A(){
System.out.println("A() before draw()");
draw();
System.out.println("A() after draw()");
}
}

class B extends A{
private int radius =1;
public B(int r) {
System.out.println("after the base constructor:"+radius);
radius=r;
System.out.println("B.B(), radius="+radius);
}
void draw(){
System.out.println("B.draw(), radius="+radius);
}
}


会出现什么结果?
A() before draw()
B.draw(), radius=0
A() after draw()
after the base constructor:1
B.B(), radius=5


调用父类构造器时,动态绑定的draw方法实际执行的是子类的draw。如果程序运行到构造器的内部,那么整个对象可能只是部分形成。[color=darkblue]这里可能造成的一个假象是:非静态成员变量的初始化发生在构造方法执行之后。这样说的理由可能是在构造器内部输出的radius的值为0。但是需要注意,radius是属于B的非静态成员变量,B.draw(), radius=0的输出结果发生在B的构造方法执行之前,这条语句是B父类的构造器输出的。after the base constructor:1才是B构造器执行的第一条语句,也是构造方法执行的一个标志,这时radius已经被初始化为1。[/color]
从这个例子可以得到的结论是:[color=red]一个动态绑定的方法调用会向外深入到继承层次结构内部,它可以调用子类里的方法。如果我们在构造器内部这样做,那么就可能会调用某个方法,而这个方法所操纵的成员可能还未进行初始化。[/color]
[list] 这个例子所展示的初始化实际过程是:
[*]在其他任何食物发生之前,将分配给对象的存储空间初始化成二进制的0
[*]调用父类的构造器,父类构造器中的draw方法实际执行的是子类重写过的draw
[*]按照声明的顺序调用成员的初始化方法
[*]调用子类的构造器
[/list]
编写构造器的一条准则是:[color=red]用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法。[/color]
在构造器内唯一能够安全调用的那些方法是父类中的final方法,因为这写方法不能被覆盖。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值