java局限性_Java泛型的局限性

Java泛型的局限性一般都是由類型擦除引起的。

1. 不能使用基本類型實例化類型參數

描述:不可以定義類似於Piar<int>這樣的類。

原因:假設泛型類為Pair,類型擦除以后為Pair,也即Pair,如果定義Pair則會出錯,因為int不能賦予Object類型的變量。

解決辦法:使用Integer,Double, Boolean, Long,Short, Character, Byte, Float

2. 不能實例化類型參數

描述:不可以new T()

原因:假設T是String,然后你准備定義String string = new T(); 但編譯器類型擦除之后,這條定義就變成String string = new Object(); 這明顯不可以。

解決辦法:使用反射。

public static T createInstance(Class clazz) {

try {

T result = clazz.newInstance();

}

catch (Exception e) {

return null

}

}3. 不可以實例化類型變量的數組

描述:不可以定義T[] array = new T[10];

原因:類型擦除后上述定義變為Object[] array = new Object[10]; 這樣一來我們可以將任何類型賦予array[0], 比如array[0] = "123"; 編譯器不會報錯,但運行時就有可能會出錯了。

解決方法:使用反射。

public static > T[] maxTwo(Class arrayElementClazz) {

// Type safety: Unchecked cast from Object[] to T[]

return (T[]) Array.newInstance(arrayElementClazz, 2) ;

}

4. 不可以定義泛型類的數組

描述:不可以定義Pair[] pairs = new Pair[10];

原因:類型擦除以后變為Pair[] pars = new Pair[10]; 然后我們可以賦予pairs[0] = new Pair(); 沒有編譯錯誤,但存在運行時錯誤。

解決方法:使用ArrayList,ArrayList> pairs = new ArrayList>();

5.不可以對泛型類型進行類型檢測,轉化

描述:不可以用a instanceof Pair,也不可以(Pair)a

原因:類型擦除后上述代碼變為 a instanceof Pair; (Pair)a,這明顯不是我們的目的;同理對於Pair pair; pair.getClass()總是返回Pair.class;

PS: Pair stringPairs = ...; Pair intPairs = ...; 那么stringPairs.getClass() == intPairs.getClass() 返回值為true

6. 不可以拋出或捕獲泛型異常

描述:既不能拋出也不能捕獲泛型類的對象。實際上,甚至泛型類型擴展throwable都是不合法的。以下都是不合法的

public class Problem extends Exception {/*...*/}

public static void doWork(Class t) { try { do work } catch (T e) { Logger.global.info(...) }}但以下方法合法:

public static void doWork(T t) throws T {

try {

do work

}

catch (Throwable realCause) {

t.initCause(realCause);

throw t;

}

}

7. 泛型類的靜態類型變量/方法無效

描述:不可以在泛型類Pair中定義public static T singleInstance;也不可以定義public static T getSingleInstance();

原因:擦除后變成

public Pair {

public static Object singleInstance; public static object getSingleInstance();}

所以類型變量對於static元素並不起作用。

8. 類型擦除引發的沖突

public class NameClash {

public boolean equals(T value) {

return false ;

}

}

從這個類的定義中來看,存在兩個equals方法,一個是自身定義的public boolean equals(T value) {...},一個是從Object繼承的public boolean equals(Object obj) {...},但類型

擦除以后,前者方法成為了public boolean equals(Object value) {...},而在一個類中同時存在兩個方法名和參數一樣的方法是不可能的,所以這里引發的沖突是沒法通過編譯

器的。可以通過重新命名方法進行修正。

擦除引起的沖突還體現在另一點上,再看一段錯誤的代碼:

class Calendar implements Comparable {...}

class GregorianCalendar extends Calendar implements Comparable {...}

上述代碼是非法的,為什么?回顧一下類型擦除后,虛擬機會為Calendar 類合成橋方法,實現了Comparable獲得一個橋方法:

public int compareTo (Object o) {return compareTo((Calendar)o);}

而實現了Comparable在類型擦除后,虛擬機為GregorianCalendar合成一個橋方法:

public int compareTo (Object o) {return compareTo((GregorianCalendar )o);}

這樣一來在GregorianCalendar類中存在兩個一樣的方法,這是不允許的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值