Java 泛型中? super T和? extends T的区别
原文鏈接? ? ? ? ??李璟(jlee381344197@gmail.com)
經常發現有List<? super T>、Set<? extends T>的聲明,是什么意思呢?<? super T>表示包括T在內的任何T的父類,<? extends T>表示包括T在內的任何T的子類,下面我們詳細分析一下兩種通配符具體的區別。
?
extends
List<? extends Number> foo3的通配符聲明,意味著以下的賦值是合法的:
| 01 | // Number "extends" Number (in this context) |
| 02 | ? |
| 03 | List<??extends?Number> foo3 =?new?ArrayList<??extends?Number>(); |
| 04 | ? |
| 05 | // Integer extends Number |
| 06 | ? |
| 07 | List<??extends?Number> foo3 =?new?ArrayList<??extends?Integer>(); |
| 08 | ? |
| 09 | // Double extends Number |
| 10 | ? |
| 11 | List<??extends?Number> foo3 =?new?ArrayList<??extends?Double>(); |
你不能保證讀取到Integer,因為foo3可能指向的是List<Double>。
你不能保證讀取到Double,因為foo3可能指向的是List<Integer>。
你不能插入一個Integer元素,因為foo3可能指向List<Double>。
你不能插入一個Double元素,因為foo3可能指向List<Integer>。
你不能插入一個Number元素,因為foo3可能指向List<Integer>。
你不能往List<? extends T>中插入任何類型的對象,因為你不能保證列表實際指向的類型是什么,你并不能保證列表中實際存儲什么類型的對象。唯一可以保證的是,你可以從中讀取到T或者T的子類。
super
現在考慮一下List<? super T>。
List<? super Integer> foo3的通配符聲明,意味著以下賦值是合法的:
| 01 | // Integer is a "superclass" of Integer (in this context) |
| 02 | ? |
| 03 | List<??super?Integer> foo3 =?new?ArrayList<Integer>(); |
| 04 | ? |
| 05 | // Number is a superclass of Integer |
| 06 | ? |
| 07 | List<??super?Integer> foo3 =?new?ArrayList<Number>(); |
| 08 | ? |
| 09 | // Object is a superclass of Integer |
| 10 | ? |
| 11 | List<??super?Integer> foo3 =?new?ArrayList<Object>(); |
你不能保證讀取到Number,因為foo3可能指向List<Object>。
唯一可以保證的是,你可以讀取到Object或者Object子類的對象(你并不知道具體的子類是什么)。
你可以插入Integer的子類的對象,因為Integer的子類同時也是Integer,原因同上。
你不能插入Double對象,因為foo3可能指向ArrayList<Integer>。
你不能插入Number對象,因為foo3可能指向ArrayList<Integer>。
你不能插入Object對象,因為foo3可能指向ArrayList<Integer>。
PECS
請記住PECS原則:生產者(Producer)使用extends,消費者(Consumer)使用super。
- 生產者使用extends
如果你需要一個列表提供T類型的元素(即你想從列表中讀取T類型的元素),你需要把這個列表聲明成<? extends T>,比如List<? extends Integer>,因此你不能往該列表中添加任何元素。
- 消費者使用super
如果需要一個列表使用T類型的元素(即你想把T類型的元素加入到列表中),你需要把這個列表聲明成<? super T>,比如List<? super Integer>,因此你不能保證從中讀取到的元素的類型。
- 即是生產者,也是消費者
如果一個列表即要生產,又要消費,你不能使用泛型通配符聲明列表,比如List<Integer>。
例子
請參考java.util.Collections里的copy方法(JDK1.7):
?
我們可以從Java開發團隊的代碼中獲得到一些啟發,copy方法中使用到了PECS原則,實現了對參數的保護。
?
原創文章,轉載請注明:?轉載自并發編程網 – ifeve.com本文鏈接地址:?泛型中? super T和? extends T的區別
總結
以上是生活随笔為你收集整理的Java 泛型中? super T和? extends T的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 泛型总结(三):通配符的使用
- 下一篇: java泛型(二)、泛型的内部原理:类型