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>來實現關聯。

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM