泛型的约束与局限性
一、不能用基本类型实例化类型参数
不能用类型参数替代基本类型。没有Paris<double>,只有,Pair<Double>。原因是类型擦除后,数据域的类型是Object,但是Object不能double类型的值。当不能用Double之类的包装器时,可以使用独立的类和方法来处理。
二、运行时类型查询只实用于原始类型
虚拟机中的对象只属于一个非泛型类型,所以类型查询时查到的结果是类型擦除后的原始类型,例如:
if(a instanceof Pair<String>) //结果为真, 类型是Pair
if(a instanceof Pair<T>)//结果也为真,类型是Pair
//强制类型转换
Pair<String> p = (Pair<String>) a;//会产生一个编译器警告,会转为原始类型Pair
//getClass()返回原始类型
Pair<String> stringPair = ...;
Pair<Employee> employeePair = ...;
if(stirngPair.getClass() == employeePair.getClass())//结果为真
三、不能抛出也不能捕获泛型实例
不能抛出也不能捕获泛型实例,泛型类继承Throwable都不合法。
public class Problem<T> extends Exception {...}
//不能再catch子句中使用类型变量,
public static <T extends Throwable> void doWork(Class <T> t){
try
{
do work
}
catch(T e)
{
Logger.glogal.info(...)
}
}
//异常申明中可以使用类型变量
public static <T extends Throwable> void doWork(T t) throws T {//OK
try
{
do work
}
catch(Throwable realCause)
{
t,initCause(realCause)
throw t;
}
}
四、参数类型化的数组不合法
不能声明这样的数组:
Pair <String>[] table = new Pair<String>[10];
错误类型的元素存入数组时会导致类型错误,但是类型擦除使得在存入错误类型的元素时,可以通过数组存储的检测,但是仍然会导致类型错误而,使得错误检查机制效率降低。
五、不能实例化类型变量
new T(...)和T.class是非法的。类型擦除会使得调用了new Object();
六、泛型类的静态上下文中类型变量无效
public class Singleton<T>
{
private static String singleInstance;//这样写是错误的
//这个方法也是错的
public static String getSingleInstance (){
if(singleInstance != null) return singleInstance;
}
}
七、注意擦除后的冲突