摘要:java 泛型轉(zhuǎn)換的事實(shí):虛擬機(jī)中沒有泛型, 只有普通的類和方法: 因?yàn)榇嬖?nbsp;類型擦除, 泛型類型被替換為限定類型(無限定類型就使用 Object), 限定類型是指 <T extends ClassName & InterfaceName & XXX>;所有的類型參數(shù)都用它們的限定類型替換;
java 泛型轉(zhuǎn)換的事實(shí):
虛擬機(jī)中沒有泛型, 只有普通的類和方法: 因?yàn)榇嬖?nbsp;類型擦除, 泛型類型被替換為限定類型(無限定類型就使用 Object), 限定類型是指
<T extends ClassName & InterfaceName & XXX>;
所有的類型參數(shù)都用它們的限定類型替換;
編譯器會(huì)生成 橋方法 以保持多態(tài);
為保持類型安全性, 必要時(shí)插入強(qiáng)制類型轉(zhuǎn)換;
java 泛型的約束和局限性:
1. 不能使用基本類型實(shí)例化類型參數(shù);
2. 運(yùn)行時(shí)類型查詢只適用于原始類型;
因?yàn)?nbsp;類型擦除, java 虛擬機(jī)中的對(duì)象沒有泛型類型這一說, instanceof 和 getClass() 只能查詢到原始類型, 具體的泛型類型時(shí)無從得知的.
3. 不能創(chuàng)建參數(shù)化類型的數(shù)組
只可聲明參數(shù)化類型的數(shù)組, 但不能創(chuàng)建參數(shù)化類型的數(shù)組.
例如 Pair<String> table = new Pair<String>[10] 是錯(cuò)誤的,
4. Varargs 警告
雖然不支持創(chuàng)建泛型類型的數(shù)組, 但由于可變參數(shù)其實(shí)是個(gè)數(shù)組, 當(dāng)向可變參數(shù)化傳遞泛型類型時(shí), 就會(huì)有這個(gè)問題.
為此 java 編譯器支持了這種情況, 但還會(huì)產(chǎn)生一個(gè)警告, 可通過 @SafeVarargs 注解抑制該警告.
5. 不能實(shí)例化類型變量
不能直接通過 new 實(shí)例化類型變量(因?yàn)?nbsp;類型擦除 后會(huì)變成 Object 類型), 這時(shí)候可借助函數(shù)式接口 Supplier<T>,
表示一個(gè)無參數(shù)且返回類型為 T 的函數(shù):
public static <T> Pair<T> makePair<Supplier<T> constr) { return new Pair<>(constr.get(), constr.get()); } Pair<String> pair = Pair.makePair(String.class);
6. 不能構(gòu)造泛型數(shù)組
7. 泛型類的靜態(tài)上下文類型變量無效
8. 不能拋出或捕獲泛型類的實(shí)例
9. 可以消除對(duì)受查異常的檢測(cè)
10. 注意類型擦除后的沖突
要想支持擦除的轉(zhuǎn)換, 就需要強(qiáng)行限制一個(gè)類或類型變量不能同時(shí)成為兩個(gè)接口類型的子類, 而這兩個(gè)接口是同一接口的不同參數(shù)化. 例如下述代碼是非法的:
class Employee implements Comparable<Employee> { ... } class Manager extends Employee implements Comparable<Manager> { ... }
Manager 會(huì)實(shí)現(xiàn) Comparable<Employee> 和 Comparable<Manager>, 這是同一接口的不同參數(shù)化.
但, 非泛型版本是合法的:
class Employee implements Comparable { ... } class Manager extends Employee implements Comparable { ... }
泛型里的通配符概念
當(dāng)知道泛型的具體類型時(shí), 使用字符 T(當(dāng)然其他字符也行).
但當(dāng)泛型的參數(shù)類型變化時(shí), 就只能使用 ? 了. 其中:
<? extends 類或接口>: 子類型限定, 只可從泛型對(duì)象讀取, 不能寫入;
<? super 類或接口>: 超類型限定, 可向泛型對(duì)象寫入, 讀取時(shí)不能保證類型(只能是 Object).