泛型(generic):聲明中具有一個或多個類型參數
原始類型(raw type):不帶任何實際類型參數的泛型名稱
格式: <code>類或接口的名稱</code> <code><</code> <code>對應于泛型形式類型參數的實際參數</code> <code>></code> 如 <code>list<string></code> 就是對應于<code>list<e></code>的實際參數為<code>string</code>的參數化類型 如與<code>list<e></code>對應的原始類型是<code>list</code>
優點:
在編譯時發現插入類型的錯誤(越早發現錯誤越好,編譯時發現好于運作時發現)
不再需要手工轉換類型
<code>list</code>和<code>list<object></code>之間的差別? <code>list</code>逃避了泛型檢查,<code>list<object></code>則是告知編譯器,它能夠持有任意類型的對象
無限制的通配符類型:
使用泛型,但不确定或者不關心實際的類型參數,可以用一個問号代替。如list<?>
學習連結: <a href="https://docs.oracle.com/javase/tutorial/java/generics/erasure.html">1.https://docs.oracle.com/javase/tutorial/java/generics/erasure.html</a> <a href="http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java">2.http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java</a>
下面通過一個小demo說明類型擦除
運作結果:
一般不在代碼中使用原始類型,除了兩種例外情況(都是因為泛型資訊在運作時會被擦除):
1.在類文字(class literals)中
<code>如: list.class,string[].class,int.class都合法 list<string>.class,list<string>.class都不合法</code>
2.instanceof
下面的表格是泛型相關的術語:
下面這張圖很好的介紹了無限制通配符和其他泛型符号之間的關系:
始終在盡可能小的範圍内使用suppresswarnings注解
java源碼中的arraylist類中有個toarray方法,其中就有強轉的警告:
最好是将範圍進一步縮小。将注解由整個方法到局部的變量聲明上去。
數組是協變的(covariant),泛型則是不可變的
數組是具體化的(reified),在運作時才知道并檢查它們的元素類型限制。而泛型通過擦除來實作的。泛型隻在編譯時強化類型資訊,并在運作時擦除它們的元素類型資訊。擦除就是使泛型可以與沒有使用泛型的代碼可以互用。
數組和泛型不能很好地混合使用。可用清單代替數組。
總結:數組是協變且可具體化的,泛型是不可變的且可被擦除的。-->數組提供了運作時類型安全而編譯時類型不安全。而泛型反之。
泛型相比于object的優點:
不需要強制類型轉換
編譯時類型安全
前面曾鼓勵優先使用清單而不是數組。并不意味着所有的泛型中都要使用清單。況且java并不是生來就支援清單的。
每個類型都是它自身的子類型。
方法可以考慮泛型化,特别是靜态工具方法。
泛型方法文法:
方法修飾語 泛型 傳回值 方法名() <code>public static <t> t foo(t args);</code>
泛型單例工廠:
遞歸類型限制:
通過某個包含該類型參數本身的表達式來限制類型參數
參數化類型是不可變的。
從上面的demo中我們知道,java中提供了<code>有限制的通配符類型</code>來提高api的靈活性。
如 collection<? extends e> collection<? super e>
一般在表示生産者或消費者的輸入參數上使用通配符類型。
pecs:producer-extends consumer-super
原文位址:http://www.cnblogs.com/johntsai/p/5344733.html