Java多態(tài)中的向上轉型與向下轉型淺析
向上轉型
概念明細
【原理】:實際就是創(chuàng)建一個子類對象,將其當成父類對象來使用.
語法格式:父類類型 對象名 = new 子類類型()
Animal animal = new Cat("元寶",2);
//animal是父類類型,但可以引用一個子類對象,因為是從小范圍向大范圍的轉換
以下是定義的父類Animal類它的兩個繼承類Cat類和Dog類,分別重寫了Animal類的eat()方法
class Animal{
String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(age + "歲的" + name + "正在吃東西");
}
}
class Cat extends Animal {
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(age + "歲的" + name + "正在吃貓糧");
}
}
class Dog extends Animal {
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(age + "歲的" + name + "正在吃狗糧");
}
}

使用場景1:直接賦值
以下這種就是直接賦值類型的向上轉型,將子類對象的引用給到父類對象。然后再將這個對象作為參數(shù)傳遞進去,就可以根據(jù)不同引用調用不同的行為
public class Test1 {
public static void eat(Animal animal)
{
animal.eat();
}
public static void main(String[] args) {
Animal animal1 = new Animal("動物",3);
Animal animal2 = new Cat("加菲貓",2);
Animal animal3 = new Dog("哈士奇",1);
eat(animal1);
eat(animal2);
eat(animal3);
}
}

使用場景2:
方法傳參 第二種方法傳參很簡單,我們連對象都不需要創(chuàng)建,只需要直接將三種不同對象的引用作為實參傳遞給到eat()中的形參接受,就可以產生【向上轉型】
public class Test1 {
public static void eat(Animal animal)
{
animal.eat();
}
public static void main(String[] args) {
eat(new Animal("動物",3));
eat(new Cat("加菲貓",2));
eat(new Dog("哈士奇",1));
}
}
使用場景3:
方法返回 第三種便是在一個方法中將不同對象的引用進行返回,然后傳遞給到父類對象,也可以產生向上轉型
public static void eat(Animal animal)
{
animal.eat();
}
稍微講一下這個方法,可以看到形參是String字符類型,在方法中通過判斷外界傳入進來的字符串然后對應地進行返回
- 若是“貓”就返Cat對象的引用;
- 若是“狗”就返Dog對象的引用;
- 若是其他就返null
public static Animal BuyAnimal(String var)
{
if(var.equals("貓")){
return new Cat("加菲貓",2);
}else if(var.equals("狗")){
return new Dog("哈士奇",1);
}else{
return null;
}
}
Animal animal1 = BuyAnimal("貓");
eat(animal1);
Animal animal2 = BuyAnimal("狗");
eat(animal2);
Animal animal3 = BuyAnimal("兔");
eat(animal3);
然后可以看到,前兩個傳入的是【貓】和【狗】,因此執(zhí)行的便是不同對象的行為,但是在最后傳入了【兔】,因此在BuyAnimal()方法中會return null
這就使得傳入eat()方法中去調用相關對象的行為時因為不存在這個對象的引用,所以就會產生空指針異常

上述便是向上轉型的三種場景。學會辨別和使用即可
向上轉型的優(yōu)缺點
【優(yōu)點】:讓代碼實現(xiàn)更簡單靈活,這個從上面的三個不同場景就可以看得出來
【缺點】:不能調用到子類特有的方法??
比如說我在Dog類中寫了一個它自己獨有的方法lookdoor()
class Dog extends Animal {
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(age + "歲的" + name + "正在吃狗糧");
}
public void lookdoor(){
System.out.println(name + "在看門");
}
}
但是可以看到,我在通過向上轉型之后通過父類對象接受子類引用但是調用不到子類中特有的方法,這其實就是向上轉型的缺陷

【注意事項】
- 上轉型對象不可以訪問子類新增的成員變量和子類自己新增的方法,因為這是子類獨有的,而父類中沒有
- 上轉型對象可以訪問子類繼承的方法或者是子類重寫的方法,這個時候當上轉型對象去調用這個方法時,一定是調用了子類重寫后的方法,這就是我們前面在講繼承的時候所提到的方法重寫
- 不可以將父類創(chuàng)建的對象的引用賦值給子類聲明的對象,也就是下面的這兩句代碼,這很明顯和我們的上轉型對象相反的,我們是將子類對象給到父類的引用,但這是將父類的引用給到子類的對象,完全就是顛倒黑白【就和貓是動物,動物卻不是貓??一個道理】
向下轉型
接下去我們來講講向下轉型,這種類型的轉化不太安全,如果沒有特殊需求,不建議使用
向下轉型解決【調用子類獨有方法】
繼續(xù)上面的談到的在向上轉型之后無法調用子類獨有的方法這個問題,其實向下轉型就可以解決,代碼如下
Animal animal1 = new Dog("哈士奇",1);
animal1.eat();
//animal1.lookdoor();
Dog dog = (Dog) animal1;
dog.lookdoor();
可以看到,也就是將父類的對象animal強轉成為Dog狗類的對象,這樣的話其實就可以去調用子類中特有的方法了

向下轉型的缺陷
那為什么說向下轉型不安全呢,因為它存在安全隱患
Animal animal1 = new Cat("加菲貓",2);
animal1.eat();
//animal1.lookdoor();
Dog dog = (Dog) animal1;
dog.lookdoor();
可以看到我將原先的Dog狗類變?yōu)榱?code>Cat貓類,此時animal就得到了貓類對象的引用,但是在下面可以看到如果將這個animal強轉為Dog狗類的對象其實就會出問題了
看到編譯器報出了ClassCastException —— 類型轉換異常

向下轉型的優(yōu)化
??向下轉型用的比較少,而且不安全,萬一轉換失敗,運行時就會拋異常。
??Java中為了提高向下轉型的安全性,引入了 instanceof ,如果該表達式為true,則可以安全轉換
可以看到,在進行強轉之前我通過instanceof這個關鍵字進行了一下判斷,看看animal1是否獲取到了Dog類的引用,若是才可以進行強制類型轉化,若不是的話就不會進行任何操作
Animal animal1 = new Cat("加菲貓",2);
animal1.eat();
//animal1.lookdoor();
if(animal1 instanceof Dog){ //判斷一下animal1是否獲取到了Dog類的引用
Dog dog = (Dog) animal1;
dog.lookdoor();
}

如果對instance關鍵字感興趣的可以看看官方的文檔 ——> instanceof關鍵字

再度對比二者【碎碎念】
可能在上面這一系列說來有點難分辨,我們再來對比看看
其實你可以這么去想Animal animal1 = new Cat可以看成是貓歸屬于一個動物類,那貓一定是屬于動物的
但是看到Dog dog = (Dog) animal1其實就要去思考把動物歸屬于狗,這其實是說不通的,難道只要是動物就一定是狗嗎?那可不一定,動物可多的是

總結與提煉
來總結一下本文所學到的內容
- 在本文中我們講到了多態(tài)中的【向上轉型】與【向下轉型】
- 首先是說到了向上轉型,介紹了它會出現(xiàn)的三種場景,也分析了它的優(yōu)缺點,知道了在向下轉型之后無法調用子類特有的方法
- 但是在向下轉型中,我們解決了這個問題,通過對父類對象進行一個強轉,就可以調用到子類當中的方法,不過可以看到這種做法不太安全,若是一開始父類對象接受了一個子類的引用,但是在強轉的時候轉化為了另外一個子類,就會造成類型轉換的問題
- 于是后面對方法進行了修正,在前面加上了instanceof關鍵字進行一個判斷,只有父類接收到了這個子類的引用,才可以強轉為這個子類的對象
到此這篇關于Java多態(tài)中的向上轉型與向下轉型的文章就介紹到這了,更多相關Java多態(tài)向上轉型與向下轉型內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring cloud 查詢返回廣告創(chuàng)意實例代碼
在本篇文章里小編給大家整理的是關于Spring cloud 查詢返回廣告創(chuàng)意實例代碼,需要的朋友們可以跟著學習下。2019-08-08

