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 修饰的不具备多态特性的方法,这样会避免以上情况的发生。
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。