java的引用類型轉換分為兩種:
- 向上類型轉換,是小類型到大類型的轉換
- 向下類型轉換,是大類型到小類型的轉換
現存在一個Animal動物類,貓子類和狗子類繼承於Animal父類;
1 public class Animal { 2 private String name; 3 4 public String getName() { 5 return name; 6 } 7 8 public void setName(String name) { 9 this.name = name; 10 } 11 12 public void eat() { 13 14 } 15 } 16 17 public class Cat extends Animal { 18 public void eatFish() { 19 System.out.println("貓吃魚"); 20 } 21 } 22 23 public class Dog extends Animal { 24 public void eatBone() { 25 System.out.println("狗吃骨頭"); 26 } 27 }
實例化一個cat對象,如下:
1 Cat cat1 = new Cat(); //使用子類引用實例化子類對象 2 3 Animal cat2 = cat1; 4 //此時為向上引用轉換,小類型轉換為大類型,並沒有風險 5 6 //Cat cat3 = cat2; //報錯 7 //由於cat2已經是Animal類的引用,所以此時為向下引用轉換,即大類型轉換為小類型,有數據溢出的風險 8 //雖然有風險,但也可以強制轉換 9 Cat cat3 = (Cat)cat2; //強制轉換成功 10 11 //Dog dog1 = cat2; //因為子類不同所以不能這樣引用 12 //Dog dog1 = (Dog)cat2; //即使強制轉換也不行
雖然向下引用轉換會存在風險,但是可以利用java的instanceof關鍵字去解決這個問題。instanceof運算符用法:判斷是一個實例對象是否屬於一個類,是返回true,否則返回false。這樣我們可以優化上面的代碼避免強制轉換類型時出現的問題:
1 /** 2 * instanceof運算符用法 3 * 運算符是雙目運算符,左面的操作元是一個對象,右面是一個類.當 4 * 左面的對象是右面的類創建的對象時,該運算符運算的結果是true,否則是false 5 * 6 * 說明:(1)一個類的實例包括本身的實例,以及所有直接或間接子類的實例 7 * (2)instanceof左邊操作元顯式聲明的類型與右邊操作元必須是同種類或右邊是左邊父類的繼承關系, 8 * (3)不同的繼承關系下,編譯出錯 9 */ 10 if(cat2 instanceof Dog) { 11 Dog dog = (Dog)cat2; 12 }else { 13 System.out.println("並不能轉換"); 14 }
但是當子類實例對象統一放進父類引用對象數組時,若要使用子類中的方法,必須先向下轉換類型為子類引用,不然編譯器會報錯
1 Animal[] animals = { 2 new Cat(), 3 new Dog() 4 }; 5 6 7 //animals[1].eatFish(); //報錯 8 if(animals[1] instanceof Cat) { 9 Cat cat = (Cat)animals[1]; 10 }