1:什么是泛型?
泛型的本質(zhì)是參數(shù)化類型的應(yīng)用,也就是說所操作的數(shù)據(jù)類型被指定為一個參數(shù)。這種參數(shù)類型可以用在類、接口和方法的創(chuàng)建中,分別稱為泛型類、泛型接口、泛型方法。而這個參數(shù)必須是引用類型。其中:
ArrayList<T>中的T稱為類型參數(shù)變量
ArrayList<Integer>中的Integer稱為實際類型參數(shù)
整個ArrayList<T>稱為泛型類型
整個ArrayList<Integer>稱為參數(shù)化的類型(ParameterizedType)
2 : 引入泛型的好處?
2.1 類型安全
泛型的主要目標是提高 Java 程序的類型安全
編譯時期就可以檢查出因 Java 類型不正確導(dǎo)致的 ClassCastException 異常
符合越早出錯代價越小原則
2.2 消除強制類型轉(zhuǎn)換
使用時直接得到目標類型,消除許多強制類型轉(zhuǎn)換,使得代碼更加可讀,并且減少了出錯機會
2.3 潛在的性能收益
由于泛型的實現(xiàn)方式,支持泛型(幾乎)不需要 JVM 或類文件更改
所有工作都在編譯器中完成
編譯器生成的代碼跟不使用泛型(和強制類型轉(zhuǎn)換)時所寫的代碼幾乎一致,只是更能確保類型安全而已
3:泛型的聲明方式
3.1 泛型類的聲明
public? class? GenericClass <T> { };
3.2 泛型接口的聲明
?interface Generic <T> { };
3.3 泛型方法的聲明
<T >? void ? get? (T? data) () {? };
4 : 用泛型實現(xiàn)元組
元組其實是關(guān)系數(shù)據(jù)庫中的一個學(xué)術(shù)名詞,一條記錄就是一個元組,一個表就是一個關(guān)系,紀錄組成表,元組生成關(guān)系,這就是關(guān)系數(shù)據(jù)庫的核心理念,在 Java 中我們?nèi)绻雰?yōu)雅實現(xiàn)元組就可以借助泛型類實現(xiàn),如下是一個三元組類型的實現(xiàn):

5:類型擦除
5.1 為什么 Java 泛型要通過擦除來實現(xiàn)?擦除有什么壞處或者說代價?
可以說 Java 泛型的存在就是一個不得已的妥協(xié),正因為這種妥協(xié)導(dǎo)致了 Java 泛型的混亂,甚至說是 JDK 泛型設(shè)計的失敗。Java 之所以要通過擦除來實現(xiàn)泛型機制其實是為了兼容性考慮,只有這樣才能讓非泛化代碼到泛化代碼的轉(zhuǎn)變過程建立在不破壞現(xiàn)有類庫的實現(xiàn)上。正是因為這種兼容也帶來了一些代價,譬如泛型不能顯式地引用運行時類型的操作之中(如向上向下轉(zhuǎn)型、instanceof 操作等),因為所有關(guān)于參數(shù)的信息都丟失了,所以任何時候使用泛型都要提醒自己背后的真實擦除類型到底是什么;此外擦除和兼容性導(dǎo)致了使用泛型并不是強制的(如 List list = new ArrayList(); 等寫法);其次擦除會導(dǎo)致我們在編寫代碼時十分謹慎(如不想被擦除為 Object 類型時不要忘了添加上邊界操作等)。
如下聲明都是錯誤的,因為泛型擦除丟失了在泛型代碼中執(zhí)行某些操作的能力,任何在運行時需要知道確切類型信息的操作都將無法工作
private void func(Object arg){
T [] aTs=new T[3];//數(shù)組中不能使用泛型
T var=new T();//實例時需要知道確切的類型信息
if(arg instanceof T){};//因為在 Java 編譯期沒法確定泛型參數(shù)化類型,也就找不到對應(yīng)的類字節(jié)碼文件,所以自然就不行了,此外由于 T 被擦除為 Object,如果可以 new T() 則就變成了 new Object(),失去了本意
}
5.2 案例分析

6:泛型中的通配符
泛型中的通配符分為如下三種:
<?>無限制通配符
<? extends T>? extends 關(guān)鍵字聲明了類型的上界,表示參數(shù)化的類型可能是所指定的類型,或者是此類型的子類
<? super T>? super 關(guān)鍵字聲明了類型的下界,表示參數(shù)化的類型可能是指定的類型,或者是此類型的父類
注意下面會報錯,因為 Java 類型參數(shù)限定只有 extends 形式,沒有 super 形式
Class Bean<T super? Number>