1. 程式人生 > 實用技巧 >java 泛型類的繼承關係和轉型問題

java 泛型類的繼承關係和轉型問題

兩個問題

問題一:FatherClass和ChildClass是父子類的關係,那List<FatherClass>和List<ChildClass>是否也是父子類的關係?

問題二:倘若不是父子類關係,那麼通過什麼方式可以達到向上轉型的效果?

有兩個類Fruit和Apple,Apple繼承自Fruit,所以Fruit使Apple的父類,關係如下圖所示

示例程式碼

public class GenericMain {

    public static void method1(Fruit fruit) {
        System.out.println("lingyejun eat fruit");
    }

    
public static void method2(List<Fruit> fruitList) { System.out.println("lingyejun eat fruit list"); } public static void method3(Collection<Fruit> fruitList) { System.out.println("lingyejun eat fruit collection"); } public static void method4(List<? extends
Fruit> fruitList) { System.out.println("lingyejun eat extends fruit list"); } public static void main(String[] args) { method1(new Fruit()); method1(new Apple()); List<Fruit> fruitList = new ArrayList<>(); fruitList.add(new Fruit()); method2(fruitList); List
<Apple> appleList = new ArrayList<>(); appleList.add(new Apple()); method2(appleList);// Compile Error method3(fruitList);// 可以向Collection<Apple>中傳入List<Apple> Set<Fruit> fruitSet = new HashSet<>(); method3(fruitSet);// 也可以向Collection<Apple>中傳入Set<Apple> method4(fruitList); method4(appleList); } }

method1的方法引數是Fruit型別,想method1方法中傳遞Fruit型別的變數或者Apple型別的變數都是可以的,因為Apple繼承自Fruit,會進行向上型別轉換。

method2的方法引數時List<Fruit>,我們試圖傳遞List<Apple>型別的變數是會出現編譯報錯,因為List<Fruit>和List<Apple>並不存在所謂的父子關係,是兩種無關的型別,所以編譯會報錯。

集合類的繼承關係

對於泛化的集合型別他們的繼承關係,以Collection<E>為例,ArrayList<E>實現了List<E>, 同時 List<E> 擴充套件自 Collections<E>。故 ArrayList<E>是 List<E>的子型別,List<E>是Collections<E> 的子型別。只要型別引數E一致,這三個類的繼承關係就得到保持。如下圖所示左右分別是Collection<Fruit>和Collection<Apple>的繼承鏈路。他們兩個是相互獨立的,沒有交叉的兩條關係鏈路,所以嘗試在method2中傳入appleList會編譯報錯。

同理,我們如果定義一個method3的引數列表為Collection<Fruit>,那麼按照集合的繼承體系,方法引數中可以傳入泛型型別為Fruit的Collection下的所有子型別。

如果有這樣的需求List<Fruit>和List<Apple>想使用同樣的方法,那麼我們該怎麼樣定義引數列表呢?

可以使用extends關鍵字來限制泛型引數的適用範圍,List<T extends Fruit> 表示泛型實際引數可以是所有繼承自Fruit的類,如lApple等。

小結

泛型類和普通類一樣,可以擴充套件或實現其他的泛型類或介面。ArrayList<E>實現了List<E>介面,一個ArrayList<Apple>可以轉化為List<Apple>,而一個ArrayList<Apple>並不是一個List<Fruit>或者ArrayList<Fruit>。

如果我們要實現List<Fruit>和List<Apple>之間的關聯,可以使用泛型萬用字元在定義方法的時候指明這個List<? extends Fruit>來實現關聯。

本篇文章如有幫助到您,請給「翎野君」點個贊,感謝您的支援。