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

探讨了Java中构造器内部调用多态方法的行为,特别是在父类构造器调用被子类重写的方法时的动态绑定特性。通过实例说明了对象初始化过程中,成员变量初始化与方法调用的顺序,以及由此可能导致的未预期行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

设想这样一个场景:在父类的构造器中调用一个动态绑定方法(假设叫做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。**如果程序运行到构造器的内部,那么整个对象可能只是部分形成。这里可能造成的一个假象是:非静态成员变量的初始化发生在构造方法执行之后。这样说的理由可能是在构造器内部输出的radius的值为0。但是需要注意,radius是属于B的非静态成员变量,B.draw(), radius=0的输出结果发生在B的构造方法执行之前,这条语句是B父类的构造器输出的。after the base constructor:1才是B构造器执行的第一条语句,也是构造方法执行的一个标志,这时radius已经被初始化为1。

从这个例子可以得到的结论是:一个动态绑定的方法调用会向外深入到继承层次结构内部,它可以调用子类里的方法。如果我们在构造器内部这样做,那么就可能会调用某个方法,而这个方法所操纵的成员可能还未进行初始化。

这个例子所展示的初始化实际过程是:
1.在其他任何事务发生之前,将分配给对象的存储空间初始化成二进制的0;
2.调用父类的构造器,父类构造器中的draw方法实际执行的是子类重写过的draw;
3.按照声明的顺序调用成员的初始化方法调用子类的构造器。

编写构造器的一条准则是:用尽可能简单的方法使对象进入正常状态,如果可以的话,避免调用其他方法。
在构造器内唯一能够安全调用的那些方法是父类中的final方法,因为这写方法不能被覆盖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值