泛型的限制
要有效地使用Java泛型,必須考慮以下限制:
無法使用基元類型實例化泛型類型
無法創建類型參數的實例
無法聲明類型為類型參數的靜態字段
無法對參數化類型使用強制類型轉換或instanceof
無法創建參數化類型的數組
無法創建、捕獲或拋出參數化類型的對象
無法重載將每個重載的形式參數類型擦除為相同原始類型的方法
無法使用基元類型實例化泛型類型考慮以下參數化類型:
class Pair{ private K key; private V value; public Pair(K key, V value) { this.key = key; this.value = value; } // ... }
創建Pair對象時,不能將基本類型替換為類型參數K或V:
Pairp = new Pair<>(8, "a"); // compile-time error
你只能將非基本類型替換為類型參數K和V:
Pairp = new Pair<>(8, "a");
請注意,Java編譯器將8自動裝箱到Integer.valueOf(8),將"a"自動裝箱到Character("a"):
Pairp = new Pair<>(Integer.valueOf(8), new Character("a"));
有關自動裝箱的詳細信息,請參閱自動裝箱和拆箱。
無法創建類型參數的實例你無法創建類型參數的實例,例如,以下代碼導致編譯時錯誤:
public staticvoid append(List list) { E elem = new E(); // compile-time error list.add(elem); }
作為解決方法,你可以通過反射創建類型參數的對象:
public staticvoid append(List list, Class cls) throws Exception { E elem = cls.newInstance(); // OK list.add(elem); }
你可以按如下方式調用append方法:
List無法聲明類型為類型參數的靜態字段ls = new ArrayList<>(); append(ls, String.class);
類的靜態字段是類的所有非靜態對象共享的類級變量,因此,類型參數的靜態字段是不允許的,考慮以下類:
public class MobileDevice{ private static T os; // ... }
如果允許類型參數的靜態字段,則以下代碼將混淆:
MobileDevicephone = new MobileDevice<>(); MobileDevice pager = new MobileDevice<>(); MobileDevice pc = new MobileDevice<>();
因為靜態字段os是由phone、pager和pc共享的,所以os的實際類型是什么?它不能同時是Smartphone、Pager和TabletPC,因此,你無法創建類型參數的靜態字段。
無法對參數化類型使用強制類型轉換或instanceof因為Java編譯器會擦除泛型代碼中的所有類型參數,所以無法驗證在運行時使用泛型類型的參數化類型:
public staticvoid rtti(List list) { if (list instanceof ArrayList ) { // compile-time error // ... } }
傳遞給rtti方法的參數化類型集是:
S = { ArrayList, ArrayList LinkedList , ... }
運行時不跟蹤類型參數,因此它無法區分ArrayList
public static void rtti(List> list) { if (list instanceof ArrayList>) { // OK; instanceof requires a reifiable type // ... } }
通常,除非通過無界通配符對其進行參數化,否則無法強制轉換為參數化類型,例如:
Listli = new ArrayList<>(); List ln = (List ) li; // compile-time error
但是,在某些情況下,編譯器知道類型參數始終有效并允許強制轉換,例如:
List無法創建參數化類型的數組l1 = ...; ArrayList l2 = (ArrayList )l1; // OK
你無法創建參數化類型的數組,例如,以下代碼無法編譯:
List[] arrayOfLists = new List [2]; // compile-time error
以下代碼說明了將不同類型插入到數組中時會發生什么:
Object[] strings = new String[2]; strings[0] = "hi"; // OK strings[1] = 100; // An ArrayStoreException is thrown.
如果你使用泛型列表嘗試相同的操作,則會出現問題:
Object[] stringLists = new List[]; // compiler error, but pretend it"s allowed stringLists[0] = new ArrayList (); // OK stringLists[1] = new ArrayList (); // An ArrayStoreException should be thrown, // but the runtime can"t detect it.
如果允許參數化列表數組,則前面的代碼將無法拋出所需的ArrayStoreException。
無法創建、捕獲或拋出參數化類型的對象泛型類不能直接或間接擴展Throwable類,例如,以下類將無法編譯:
// Extends Throwable indirectly class MathExceptionextends Exception { /* ... */ } // compile-time error // Extends Throwable directly class QueueFullException extends Throwable { /* ... */ // compile-time error
方法無法捕獲類型參數的實例:
public staticvoid execute(List jobs) { try { for (J job : jobs) // ... } catch (T e) { // compile-time error // ... } }
但是,你可以在throws子句中使用類型參數:
class Parser無法重載將每個重載的形式參數類型擦除為相同原始類型的方法{ public void parse(File file) throws T { // OK // ... } }
一個類不能有兩個在類型擦除后具有相同的簽名的重載方法。
public class Example { public void print(SetstrSet) { } public void print(Set intSet) { } }
重載將共享相同的類文件表示,并將生成編譯時錯誤。
上一篇:類型擦除 下一篇:創建和使用包文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72952.html
摘要:引用泛型除了方法因不能使用外部實例參數外,其他繼承實現成員變量,成員方法,方法返回值等都可使用。因此,生成的字節碼僅包含普通的類,接口和方法。 為什么要使用泛型程序設計? 一般的類和方法,只能使用具體的類型:要么是基本類型,要么是自定義類的對應類型;如果要編寫可以應用于多種類型的代碼,這種刻板的限制對代碼的束縛就會很大。----摘自原書Ordinary classes and meth...
類型擦除 泛型被引入到Java語言中,以便在編譯時提供更嚴格的類型檢查并支持通用編程,為了實現泛型,Java編譯器將類型擦除應用于: 如果類型參數是無界的,則用它們的邊界或Object替換泛型類型中的所有類型參數,因此,生成的字節碼僅包含普通的類、接口和方法。 如有必要,插入類型轉換以保持類型安全。 生成橋接方法以保留擴展泛型類型中的多態性。 類型擦除確保不為參數化類型創建新類,因此,泛型不會...
摘要:虛擬機中并沒有泛型類型對象,所有的對象都是普通類。其原因就是泛型的擦除。中數組是協變的,泛型是不可變的。在不指定泛型的情況下,泛型變量的類型為該方法中的幾種類型的同一個父類的最小級,直到。 引入泛型的主要目標有以下幾點: 類型安全 泛型的主要目標是提高 Java 程序的類型安全 編譯時期就可以檢查出因 Java 類型不正確導致的 ClassCastException 異常 符合越早出...
摘要:使用表示泛型中的基本思想就是可以通過使用像這樣適當的超類來實現泛型類。請看例子使用實現泛型使用接口類型表示泛型當有多個類要在一個通用的方法里表示泛型時,來表示可能就顯得捉襟見肘了,因為這個時候無法明確的知道用戶到底需要拆箱為哪種類。 1.1 使用Object表示泛型 Java中的基本思想就是可以通過使用像Object這樣適當的超類來實現泛型類。--《數據結構與算法分析 Java語言描述...
閱讀 1148·2021-11-24 10:43
閱讀 3102·2021-11-22 09:34
閱讀 3549·2021-10-08 10:04
閱讀 3932·2021-09-23 11:58
閱讀 3114·2019-08-30 15:44
閱讀 483·2019-08-30 13:01
閱讀 1155·2019-08-28 18:07
閱讀 1447·2019-08-26 13:42