1. 程式人生 > >java泛型中extends 和 super的區別

java泛型中extends 和 super的區別

一般對反省中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子型別限定的萬用字元可以向泛型物件讀取。