有時候需要把父類對象指向子類對象,有時候需要把父類對象轉換成子類對象。例如我們可以說某一隻狗是一隻動物,還可以說這隻動物是一條狗,但前提是我們要知道狗肯定是動物,而那隻動物必須是一隻狗。下面介紹如何把父類指向子類對象,如何把子類對喜愛那個強制轉換成子類對象。
1、父類引用指向子類對象
正常情況下,我們會定義某個類的對象引用,然後使用new執行個體化一個對象,然後把這個引用指向該執行個體。例如:
Dog dog = new Dog();
假設Dog是Animal的子類,也可以寫下面的代碼:
Animal animal = new Dog();
Animal animal定義了一個Animal對象引用,new Dog()執行個體化了一隻狗,然後animal指向了這隻狗。 這是允許的,就像我們指著一隻狗,然後說它是動物,它確實是動物。
還可以寫成下面的形式:
Animal animal = dog;
意思是把animal引用指向dog引用指向的執行個體。
這就是向上轉型,不僅僅是父類可以指向子類的對象,只要是祖先類都可以指向子類的執行個體。典型情況,Object是所有類的祖先類,所以Object類型的對象引用可以指向任何對象。例如下面的代碼:
Object o = new Dog();
把父類引用指向子類對象的好處是什麼呢?自己可以思考一下,後面的多態性應用中詳細介紹。
另外,類似的用法還有:
某個方法的定義如下:
public void setValue(Object o){
this.value = o;
}
這個方法的參數是Object類型,傳回值類型是Object。因為參數類型是Object,所以在調用這個方法的時候我們可以給它傳遞任何類型的參數,包括上面的Dog對象,只要是它的子孫類就可以了。
再看下面的方法:
public Object getValue(){
return value;
}
value可以是任何類型,Dog執行個體,Animal執行個體,Date執行個體,Person執行個體都可以。
想想資料結構中的鏈表、隊列等等,他們的元素可以是各種類型,就可以使用這種方式,可以設定整數鏈表、Dog鏈表,擷取它的元素的時候,傳回值的類型由元素類型決定,所以參數和傳回值類型都應該設定為Object。
總結一句話:任何需要父類對象地方都可以給子類對象。
2、強制類型轉換
我們可以把父類引用指向子類對象,但是這樣帶來的其他問題。假設Dog有一個特殊的行為方法f,如果把Dog執行個體賦值給了Animal引用,例如下面的代碼:
Animal animal = new Dog();
如何訪問Dog的f方法呢?
直接寫animal.f()肯定不行,編譯不能通過,因為animal沒有方法f()。
所以這時候還需要把animal再轉換成Dog才可以存取方法f。能這樣寫嗎?
Dog d = animal;
不能,變異的時候就會報錯類型不符。可以使用下面的代碼:
Dog d = (Dog)animal;
強制把animal轉換成了Dog,也就是把動物轉換成了狗。這就是強制類型轉換,把父類對象轉換成子類對象(子類對象引用指向了父類對象)。
能轉換嗎?因為我們知道這隻動物確實是狗,所以可以轉換。
再看下面的代碼:
Animal animal = new Cat();
Dog d = (Dog)animal;
單從第2行看,與之前的代碼沒有區別。但是大家一看就知道有問題,因為代碼想把貓轉換成狗,這時候會報錯的:ClassCastException
這種錯誤不是語法錯誤,所以能夠編譯通過,但是在啟動並執行時候出錯。
所以在進行強型別轉換的時候,我們要確保能夠轉換,只有當父類指向的執行個體是某個子類的對象的時候才可以轉換成該類的對象。
如果不能確定可以通過instanceof操作符進行判斷。
if(animal instanceof Dog)
Dog d = (Dog)animal;
上一次: 第三十九講 多態
下一次:第四十一講 this和super
李緒成 CSDN Blog:http://blog.csdn.net/javaeeteacher邀請您為好友:http://student.csdn.net/invite.php?u=124362&c=7be8ba2b6f3b6cc5