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