泛型中<? extends T>和<? super T> 差別
<? extends T>和<? super T>含有JAVA5.0的新的概念。由於它們的外表導致了很多人誤解了它們的用途:
1.<?
extends T>首先你很容易誤解它爲繼承於T的所有類的集合,這是大錯特錯的,相信能看下去你一定見過或用過List<?
extends T>吧?爲什麼我說理解成一個集合是錯呢?如果理解成一個集合那爲什麼不用List<T>來表示?所以<?
extends
T>不是一個集合,而是T的某一種子類的意思,記住是一種,單一的一種,問題來了,由於連哪一種都不確定,帶來了不確定性,所以是不可能通過
add()來加入元素。你或許還覺得爲什麼add(T)不行?因爲<? extends
T>是T的某種子類,能放入子類的容器不一定放入超類,也就是沒可能放入T。
2.<? super T>這裏比較容易使用,沒<? extends T>這麼多限制,這裏的意思是,以T類爲下限的某種類,簡單地說就是T類的超類。但爲什麼add(T)可以呢?因爲能放入某一類的容器一定可以放入其子類,多態的概念。
擦除
也
許泛型最具挑戰性的方面是擦除(erasure),這是 Java
語言中泛型實現的底層技術。擦除意味着編譯器在生成類文件時基本上會拋開參數化類的大量類型信息。編譯器用它的強制類型轉換生成代碼,就像程序員在泛型出
現之前手工所做的一樣。區別在於,編譯器開始已經驗證了大量如果沒有泛型就不會驗證的類型安全約束。
通過擦除實現泛型的含意是很重要的,並
且初看也是混亂的。儘管不能將List<Integer> 賦給List<Number>,因爲它們是不同的類型,但是
List<Integer> 和 List<Number> 類型的變量是相同的類!要明白這一點,請評價下面的代碼:
new List<Number>().getClass() == new List<Integer>().getClass()
編譯器只爲 List 生成一個類。當生成了 List 的字節碼時,將很少剩下其類型參數的的跟蹤。
當
生成泛型類的字節碼時,編譯器用類型參數的擦除替換類型參數。對於無限制類型參數(<V>),它的擦除是
Object。對於上限類型參數(<K extends Comparable<K>>),它的擦除是其上限(在本例中是
Comparable)的擦除。對於具有多個限制的類型參數,使用其最左限制的擦除。
如果檢查生成的字節碼,您無法說出 List<Integer> 和 List<String> 的代碼之間的區別。類型限制 T 在字節碼中被 T 的上限所取代,該上限一般是 Object。
多重限制
一個類型參數可以具有多個限制。當您想要約束一個類型參數比如說同時爲 Comparable 和 Serializable 時,這將很有用。多重限制的語法是用“與”符號分隔限制:
class C<T extends Comparable<? super T>&Serializable>
通配符類型可以具有單個限制 —— 上限或者下限。一個指定的類型參數可以具有一個或多個上限。具有多重限制的類型參數可以用於訪問它的每個限制的方法和域。
類型形參和類型實參
在
參數化類的定義中,佔位符名稱(比如 Collection<V> 中的 V)叫做類型形參(type
parameter),它們類似於方法定義中的形式參數。在參數化類的變量的聲明中,聲明中指定的類型值叫做類型實參(type
argument),它們類似於方法調用中的實際參數。但是實際中二者一般都通稱爲“類型參數”。所以給出定義:
interface Collection<V> { ... }
和聲明:
Collection<String> cs = new HashSet<String>();
那麼,名稱 V(它可用於整個 Collection 接口體內)叫做一個類型形參。在 cs 的聲明中,String 的兩次使用都是類型實參(一次用於 Collection<V>,另一次用於 HashSet<V>)。
關
於何時可以使用類型形參,存在一些限制。大多數時候,可以在能夠使用實際類型定義的任何地方使用類型形參。但是有例外情況。不能使用它們創建對象或數組,
並且不能將它們用於靜態上下文中或者處理異常的上下文中。還不能將它們用作父類型(class Foo<T> extends
T),不能用於 instanceof 表達式中,不能用作類常量。
類似地,關於可以使用哪些類型作爲類型實參,也存在一些限制。類型實參
必須是引用類型(不是基本類型)、通配符、類型參數,或者其他參數化類型的實例化。所以您可以定義
List<String>(引用類型)、List<?>(通配符)或者
List<List<?>>(其他參數化類型的實例化)。在帶有類型形參 T 的參數化類型的定義中,您也可以聲明
List<T>(類型形參)。
泛型中
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章
Java集合框架02——線程安全的集合詳解
shenxiaolinil
2020-07-08 06:59:18
Guava 之 Multiset
PZHU_CG_csdn
2020-06-23 22:00:12
java linkedlist 使用
pingnanlee
2020-06-16 03:30:49
Java 集合:Map 系列(HashMap,HashTable)
Allen215902
2020-06-15 16:21:00
面試連環炮:HashMap線程不安全 怎麼解決?你來說說ConcurrentHashMap怎麼就安全(萬字長文)
zyk1.
2020-04-27 07:26:18
一文淺析---從面試題連環炮的角度梳理HashMap
zyk1.
2020-04-24 06:19:41
java集合框架02——Collection架構與源碼分析
shenxiaolinil
2020-04-03 01:48:56
Java集合框架01——總體框架一覽
shenxiaolinil
2020-04-03 01:48:56
Java 集合:Map 系列(ConcurrentHashMap概念)
Allen215902
2020-02-26 02:53:58
java hashset 原理
pingnanlee
2020-02-23 23:53:17
java hashset 使用
pingnanlee
2020-02-23 23:53:17
java linkedlist 原理
pingnanlee
2020-02-23 23:53:17
Java List集合比較
Kerwin1321
2020-02-23 01:14:20
HashMap,HashTable,TreeMap,WeakHashMap的區別
Anny的诺言
2020-02-20 21:52:46