天天看點

Java泛型通配符extends與super

java 泛型關鍵字說明

  • ? 通配符類型
  • <? extends T> 表示類型的上界,表示參數化類型的可能是T 或是 T的子類
  • <? super T> 表示類型下界(Java Core中叫超類型限定),表示參數化類型是此類型的超類型(父類型),直至Object

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 Fruit> 表示 “具有任何從Fruit繼承類型的清單”,編譯器無法确定List所持有的類型,是以無法安全的向其中添加對象。可以添加null,因為null 可以表示任何類型。是以List 的add 方法不能添加任何有意義的元素,但是可以接受現有的子類型List 指派。

Fruit fruit = flist.get(0);
Apple apple = (Apple)flist.get(0);
           

由于,其中放置是從Fruit中繼承的類型,是以可以安全地取出Fruit類型。

flist.contains(new Fruit());
flist.contains(new Apple());
           

在使用Collection中的contains 方法時,接受Object 參數類型,可以不涉及任何通配符,編譯器也允許這麼調用。

extends控制了元素的傳回類型,是以在以下場景使用

List<Apple> lstApple = new ArrayList<>();
List<? extends Fruit> lstFruit;
lstFruit = lstApple;//可以将具體子類型的List賦給泛型list,在添加完成後就隻能取值
lstApple.add(new Apple());
lstApple.add(new Apple());
System.out.println(lstFruit.get(0));
           

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.

// compile error:
Fruit item = flist.get(0);
           

因為,List<? super Fruit>中的類型可能是任何Fruit 的超類型,是以編譯器無法确定get傳回的對象類型是Fruit,還是Fruit的父類Food 或 Object.

小結

  • extends 可用于的傳回類型限定,不能用于參數類型限定。不能添加元素,隻能傳回
  • super 可用于參數類型限定,不能用于傳回類型限定。可以添加元素,隻能傳回Object類型
  • 帶有super超類型限定的通配符可以向泛型對象寫入,帶有extends子類型限定的通配符可以向泛型對象讀取