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

兩個問題

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

問題二:假若不是父子類關係,那麼經過什麼方式能夠達到向上轉型的效果?ui

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

示例代碼code

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,會進行向上類型轉換。blog

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下的全部子類型。rem

 若是有這樣的需求List<Fruit>和List<Apple>想使用一樣的方法,那麼咱們該怎麼樣定義參數列表呢?it

能夠使用extends關鍵字來限制泛型參數的適用範圍,List<T extends Fruit> 表示泛型實際參數能夠是全部繼承自Fruit的類,如lApple等。io

小結

泛型類和普通類同樣,能夠擴展或實現其餘的泛型類或接口。ArrayList<E>實現了List<E>接口,一個ArrayList<Apple>能夠轉化爲List<Apple>,而一個ArrayList<Apple>並非一個List<Fruit>或者ArrayList<Fruit>。

若是咱們要實現List<Fruit>和List<Apple>之間的關聯,能夠使用泛型通配符在定義方法的時候指明這個List<? extends Fruit>來實現關聯。

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

相關文章
相關標籤/搜索