java泛型中extends 和 super的區別
阿新 • • 發佈:2019-01-31
一般對反省中extends 和 super 的區別是這樣介紹的:
關鍵字說明
- ? 萬用字元型別
- <? extends T> 表示型別的上界,表示引數化型別的可能是T 或是 T的子類
- <? super T> 表示型別下界(Java Core中叫超型別限定),表示引數化型別是此型別的超型別(父型別),直至Object
List<? extends T> 是說 這個list放的是T或者T的子型別的物件,但是不能確定具體是什麼型別,所以可以get(),不能add()(可以add null值)
List<? super T> 是說這個list放的是至少是T型別的物件,所以我可以add T或者T的子型別,但是get得到的型別不確定,所以不能get
引用下網上遍地的例子
extends 示例
static class Food{} static class Fruit extends Food{} static class Apple extends Fruit{} static class RedApple extends Apple{} List<? extends Fruit> flist = new ArrayList<Apple>(); // complie error: // flist.add(new Apple()); // flist.add(new Fruit()); // flist.add(new Object()); flist.add(null); // only work for null
List<? extends Frut> 表示 “具有任何從Fruit繼承型別的列表”,編譯器無法確定List所持有的型別,所以無法安全的向其中新增物件。可以新增null,因為null 可以表示任何型別。所以List 的add 方法不能新增任何有意義的元素,但是可以接受現有的子型別List<Apple> 賦值。
Fruit fruit = flist.get(0);
Apple apple = (Apple)flist.get(0);
由於,其中放置是從Fruit中繼承的型別,所以可以安全地取出Fruit型別。
flist.contains(new Fruit()); flist.contains(new Apple());
在使用Collection中的contains 方法時,接受Object 引數型別,可以不涉及任何萬用字元,編譯器也允許這麼呼叫。
super 示例
List<? super Fruit> flist = new ArrayList<Fruit>();
flist.add(new Fruit());
flist.add(new Apple());
flist.add(new RedApple());
// compile error:
List<? super Fruit> flist = new ArrayList<Apple>();
List<? super Fruit> 表示“具有任何Fruit超型別的列表”,列表的型別至少是一個 Fruit 型別,因此可以安全的向其中新增Fruit 及其子型別。由於List<? super Fruit>中的型別可能是任何Fruit 的超型別,無法賦值為Fruit的子型別Apple的List<Apple>.
// compile error:
Fruit item = flist.get(0);
因為,List<? super Fruit>中的型別可能是任何Fruit 的超型別,所以編譯器無法確定get返回的物件型別是Fruit,還是Fruit的父類Food 或 Object.
小結
extends 可用於的返回型別限定,不能用於引數型別限定。
super 可用於引數型別限定,不能用於返回型別限定。
>帶有super超型別限定的萬用字元可以向泛型對易用寫入,帶有extends子型別限定的萬用字元可以向泛型物件讀取。