Java泛型的局限性
来源:互联网 发布:网络摄像头id 编辑:程序博客网 时间:2024/05/17 23:24
Java泛型的局限性一般都是由类型擦除引起的。
1. 不能使用基本类型实例化类型参数
描述:不可以定义类似于Piar<int>这样的类。
原因:假设泛型类为Pair<T>,类型擦除以后为Pair,也即Pair<Object>,如果定义Pair<int>则会出错,因为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> T createInstance(Class<T> 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 extends Comparable<T>> T[] maxTwo(Class<T> arrayElementClazz) { // Type safety: Unchecked cast from Object[] to T[] return (T[]) Array.newInstance(arrayElementClazz, 2) ; }
4. 不可以定义泛型类的数组
描述:不可以定义Pair<String>[] pairs = new Pair<String>[10];原因:类型擦除以后变为Pair[] pars = new Pair[10]; 然后我们可以赋予pairs[0] = new Pair<Integer>(); 没有编译错误,但存在运行时错误。
解决方法:使用ArrayList,ArrayList<Pair<String>> pairs = new ArrayList<Pair<String>>();
5.不可以对泛型类型进行类型检测,转化
描述:不可以用a instanceof Pair<String>,也不可以(Pair<String>)a
原因:类型擦除后上述代码变为 a instanceof Pair; (Pair)a,这明显不是我们的目的;同理对于Pair<String> pair; pair.getClass()总是返回Pair.class;
PS: Pair<String> stringPairs = ...; Pair<Integer> intPairs = ...; 那么stringPairs.getClass() == intPairs.getClass() 返回值为true
6. 不可以抛出或捕获泛型异常
描述:既不能抛出也不能捕获泛型类的对象。实际上,甚至泛型类型扩展throwable都是不合法的。以下都是不合法的
public class Problem<T> extends Exception {/*...*/}
public static <T extends Throwable> void doWork(Class<T> t) { try { do work } catch (T e) { Logger.global.info(...) }}但以下方法合法:
public static <T extends Throwable> void doWork(T t) throws T { try { do work } catch (Throwable realCause) { t.initCause(realCause); throw t; }}
7. 泛型类的静态类型变量/方法无效
描述:不可以在泛型类Pair<T>中定义public static T singleInstance;也不可以定义public static T getSingleInstance();
原因:擦除后变成
public Pair {public static Object singleInstance; public static object getSingleInstance();}所以类型变量对于static元素并不起作用。
8. 类型擦除引发的冲突
public class NameClash<T> { 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<Calendar> {...} class GregorianCalendar extends Calendar implements Comparable<GregorianCalendar> {...}
public int compareTo (Object o) {return compareTo((Calendar)o);}
而实现了Comparable<GregorianCalendar >在类型擦除后,虚拟机为GregorianCalendar合成一个桥方法:
public int compareTo (Object o) {return compareTo((GregorianCalendar )o);}
这样一来在GregorianCalendar类中存在两个一样的方法,这是不允许的。
- Java泛型的局限性
- Java泛型的约束和局限性
- 泛型的局限性
- Java 泛型 泛型的约束与局限性
- java泛型使用时的约束与局限性
- Java Foreach的局限性
- 泛型的约束与局限性
- java泛型编程学习 笔记二:使用泛型的约束和局限性
- Java泛型解析(04):约束和局限性
- java泛型程序设计——约束与局限性
- JAVA操作EXCEL的一些局限性
- JAVA操作EXCEL的一些局限性
- Java基础 for循环增强语句的局限性
- java泛型II-泛型中存在的约束与局限性
- Matlab Compiler 的局限性
- 公司的局限性
- SQLite的局限性
- 浅谈CUDA的局限性
- VC/VC++的学习之路二生成动态库和静态库
- struts2-----访问web元素的三种方式and 常用返回类型
- Spring常用注解介绍【经典总结】
- Python函数参数到底是按值还是按引用
- KMP的Java实现
- Java泛型的局限性
- 大神的博客
- Linux下简单的shell编程(1)
- rigibody over 翻译
- (hdu1787)GCD Again(欧拉函数)
- 转自:王垠 编程的智慧
- 在ROS中配置路由器的动态域名?
- 面向对象基础
- javax.el.PropertyNotFoundException: Property 'reviewcontent' not found on type javabean.YbReview解决方法