构造器中的多态行为


   java中,多态只会发生于非final/private的方法中,static 方法、属性、构造器、private/final方法都不具备多态行为。但是,当构造器中出现多态时,常常引起不必要的且难以发现的麻烦。看如下实例:

public class Animal {

    Animal() {
        System.out.println("Animal start to run");
        run();
        System.out.println("Animal end  run ");
    }

    void run() {
        System.out.println("Animal.run");
    }

}

class Cat extends Animal {

    private String name = "喵喵";

    Cat(String name) {
        this.name = name;
        System.out.println("Cat.Cat,init name" + this.name);
    }

    @Override
    void run() {

        System.out.println(name + " Cat.run");
    }

    public static void main(String[] args) {
        new Cat("豆豆");
    }

}

运行如上程序,我们会发现,以下结果:

Animal start to run
null Cat.run
Animal end  run 
Cat.Cat,init name豆豆

我们发现,在初始化Cat时,我们预想,初始化父类对象时,将会调用Cat重写的run方法,并打印出 “喵喵 Cat.run”,但是结果却是出乎预料,而是“null Cat.run”。

那么是什么导致这个结果呢?这个其实原因与java对象初始化顺序有关。

第一:初始化子类对象时,总是先向上初始化父类对象。级别越高,越先初始化,Object最先被初始化。本例中,在初始化Cat对象时,那么先调用父类对象Animal的构造器,来初始化父类对象。那么当程序运行至run方法时,将调用子类Cat重写后的run方法。

第二:类中的成员变量,依据声明顺序初始化。本例中,Cat 构造器默认第一句调用Animal构造器,此时,Cat尚未被初始化,Cat中的成员变量name 只是分配了内存地址并被系统赋予默认值,此时为null。

        鉴于以上原因,在Animal初始化时调用run方法时,name仍然没有被初始化,故而,输出了与预想不同的结果。

总结:在父类中调用会产生多态效果的方法时,应当谨慎,甚至避免调用此类方法。在父类构造器中,应当调用private ,final ,static 修饰的不具备多态特性的方法,这样会避免以上情况的发生。





注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告