向上轉型和向下轉型

簡單使用

聲明一個父類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

  1. 正確的向下轉型
Fruit a=new Apple(); //向上轉型
        a.myName();
        
        Apple aa=(Apple)a; //向下轉型,編譯和運行皆不會出錯(正確的)
        aa.myName();//向下轉型時調用的是子類的

a指向子類的對象,因此子類的實例aa也能夠指向acode

向下轉型後由於都是指向子類對象,因此調用的固然全是子類的方法對象

  1. 錯誤的向下轉型
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

相關文章
相關標籤/搜索