JAVA构造函数内调用多态方法

本文探讨了Java构造函数内调用多态方法的问题。在构造B类时,A类构造函数调用的print()方法实际上执行的是B类的重写方法,但由于构造过程尚未完成,成员变量i未初始化,故打印结果为B0。为避免此类情况,建议将父类的同名方法声明为private。此外,还分析了构造过程中多态调用的细节和可能引发的异常,强调了在构造器中使用private方法的重要性。

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

看如下程序代码段:

public class Test1 {
    public static void main(String[] args) {
        A b = new B();
        b.print();
    }
}

class A {
    public A(){
        print();
    }
    public void print(){
        System.out.println("A");
    }
}
class B extends A{
    int i = 1;
    public B(){
        print();
    }
    public void print(){
        System.out.println("B" + i);
    }
}
程序运行结果如下:



运行过程解释:

在构造B的时候,会先构造A,在A的构造函数中调用了print()方法,print()方法在B中被重写了,A的构造函数中实际上调用的是B中重写的print()方法,但输出为什么是B0,而不是B1呢?这是因为此时,A还没有构造完成,B更加没有构造完成,变量i是B中的成员变量,此时变量i还没有被初始化,所以其值为默认值0,所以打印出B0。

之后的就好理解了,构造B时,先会初始化成员变量i,i=1,之后执行构造函数,打印出B1。

后面的,根据多态,打印出B1,没有问题。


为了避免父类的构造函数调用子类的多态方法,一般可以将父类的同名函数申明为private,这样在父类构造函数中调用时就是调用的自己的方法。



有一点要注意的是,此时b.print()不能通过编译(图中将其注释了),这是因为b是A类型的引用,print在A中是private的,无法访问。如果将b改为B类型的(B b = new B())则可以了。


总结:

如果要在构造器中调用一个方法时,将该方法声明为private。 
假使你的父类构造器中要调用一个非静态方法,而这个方法不是private的又被子类所重载,这样在实际创建子类的过程中递归调用到了父类的构造器时,父类构造器对这个方法的调用就会由于多态而实际上调用了子类的方法,当这个子类方法需要用到子类中实例变量的时候,就会由于变量没有初始化而出现异常(至于为什么子类中的实例变量没有初始化可以参考上边的实例初始化过程),这是Java不想看到的情况。而当父类构造器中调用的方法是一个private方法时,多态就不会出现,也就不会出现父类构造器调用子类方法的情况,这样可以保证父类始终调用自己的方法,即使这个方法中调用了父类中的实例变量也不会出现变量未初始化的情况(变量初始化总是在当前类构造器主体执行之前进行)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值