這個問題一直困擾了我很久,現在抽空整理一下。一家之言,難免有錯誤之處,歡迎糾錯。
拿經常舉的例子來說,定義一個Animal類,然後定義一個類Dog繼承自Animal,定義一個Cat類也繼承自Animal,他們的繼承關系如下:
Animal
├Dog
└Cat
1.向上轉型
對于Animal animal=new Dog();這句話而言,這是典型的“父類引用指向子類對象”,也就是“向上轉型”。
向上轉型時,應該注意兩個問題:
(1).向上轉型時,子類對象被轉成父類對象,那麼隻能調用父類的成員,但是如果子類重寫了父類的方法,那麼該引用就指向了子類的重寫方法,這個轉換的過程叫做“動态綁定”。
(2).向上轉型時,這個引用會丢失除了與父類共有的其他方法,也就是在轉型的過程中,子類的所有新增加的方法都會遺失掉。編譯時會提示有錯誤。
例子:
class Animal{
public void fun(){
System.out.println("Animal......");
}
}
class Dog extends Animals{
public void fun(){
System.out.println("Dog......");
}
public void fun2(){
System.out.println("Dog has four legs.");
}
}
public class TestCastUp{
Animal animal=new Dog();//向上轉型,父類引用指向子類對象
animal.fun();//這個會輸出“Dog”,原因是動态綁定
animal.fun2();//編譯不通過,提示找不到方法
}
2.向下轉型
如果是子類引用直接執行父類對象,形如這樣的:Dog dog=new Animal();這樣的話,java不允許這樣做,編譯就通不過,提示can't convert Animal to Dog.
如果是父類引用指向父類對象,然後再向下轉型,形如這樣的:Animal animal=new Animal; Dog dog=(Dog)animal;這種轉型是不安全的,編譯不會報錯,但是運作也會報java.lang.ClassCastException這種錯誤。
那麼怎樣的向下轉型才是安全并且運作時不會報錯呢?有兩種方式:
(1).先向上轉型,再向下轉型,形如:Animal animal=new Dog(); Dog dog=(Dog)animal;
(2).運用instanceof判斷語句,形如:Animal animal=new Animal(); if(animal instanceof Dog) {.......}