聲明一個父類Father,子類Son繼承Fatherjava
Father a = new Son() // 父類引用、子類對象(向上轉型) Son b = (Son)a // 向下轉型,強制轉換 // 父類引用轉成子類引用
public class Animal { public void eat(){ System.out.println("animal eatting..."); } } class Bird extends Animal{ public void eat(){ System.out.println("bird eatting..."); } public void fly(){ System.out.println("bird flying..."); } } class Main{ public static void main(String[] args) { Animal b=new Bird(); //向上轉型 b.eat(); // 調用的是子類eat() //! error: b.fly(); // b雖指向子類對象,但此時子類做爲向上轉型的代價丟失和父類不一樣的fly()方法------ dosleep(new Male()); dosleep(new Female()); } public static void dosleep(Human h) { h.sleep(); } }
public class Human { public void sleep() { System.out.println("Human sleep.."); } } class Male extends Human { @Override public void sleep() { System.out.println("Male sleep.."); } } class Female extends Human { @Override public void sleep() { System.out.println("Female sleep.."); } }
這裏就能夠看出向上轉型的好處和使用場景了編程
public static void dosleep(Human h) { h.sleep(); }
這裏的參數類型是父類,傳入的值是子類,這就完成了向上轉型操做。而後會自動判斷調用該子類的對應方法。試想,若是咱們這麼幹安全
public static void dosleep(Male male) { male.sleep(); } public static void dosleep(Female fe) { fe.sleep(); } ......
這是人,要換成水果,給你來個幾百種,不寫死纔怪。
所以向上轉型很好的簡化了代碼,也正是體現了java的抽象編程思想,使代碼變得解耦。ide
class Fruit { public void myName() { System.out.println("我是父類 水果..."); } } class Apple extends Fruit { @Override public void myName() { System.out.println("我是子類 蘋果..."); } public void myMore() { System.out.println("我是你的小呀小蘋果~~~~~~"); } } public class Sys{ public static void main(String[] args) { Fruit a=new Apple(); //向上轉型 a.myName(); Apple aa=(Apple)a; //向下轉型,編譯和運行皆不會出錯(正確的) aa.myName();//向下轉型時調用的是子類的 aa.myMore();; Fruit f=new Fruit(); Apple aaa=(Apple)f; //-不安全的---向下轉型,編譯無錯但會運行會出錯 aaa.myName(); aaa.myMore(); } }
輸出:ui
我是子類 蘋果... 我是子類 蘋果... 我是你的小呀小蘋果~~~~~~ Exception in thread "main" java.lang.ClassCastException: com.sheepmu.Fruit cannot be cast to com.sheepmu.Apple at com.sheepmu.Sys.main(Sys.java:30)
解釋:.net
Fruit a=new Apple(); //向上轉型 a.myName(); Apple aa=(Apple)a; //向下轉型,編譯和運行皆不會出錯(正確的) aa.myName();//向下轉型時調用的是子類的
a指向子類的對象,因此子類的實例aa也能夠指向acode
向下轉型後由於都是指向子類對象,因此調用的固然全是子類的方法對象
Fruit f=new Fruit(); Apple aaa=(Apple)f; //-不安全的---向下轉型,編譯無錯但會運行會出錯 aaa.myName(); aaa.myMore();
這裏f指向父類對象,子類實例確定不能指向fblog
3.Java爲了解決不安全的向下轉型問題,引入泛型的概念繼承
4.爲了安全的類型轉換,最好先用 if(A instanceof B) 判斷一下對象類型
例:
if (f instanceof Apple){ Apple aaa=(Apple)f; aaa.myName(); aaa.myMore(); }
參考文章:https://blog.csdn.net/sheepmu/article/details/38327205