java泛型中存在一定的约束和局限性,这些限制的主要原因是java虚拟机中对泛型的处理机制有关,即类型擦除。
1:不能用基本类型实例化类型参数
主要原因就是:类型擦除引起的,ArrayList会被转为Object,但double没有继承object。
如:ArrayList<Double> list=new ArrayList<>();//正确 ArrayList<double> list=new ArrayList<>();//错误
2:运行时类型查询只适合用于原始类型
public class test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<String> list=new ArrayList<>();
ArrayList<Integer> list2=new ArrayList<>();
System.out.println(list.getClass()==list2.getClass());
System.out.println(list.getClass().getName());
}
}
运行结果:
true
java.util.ArrayList
通过运行结果发现:
两次调用的getClass都返回的java.util.ArrayList,因此在泛型中类型查询返回的是泛型的原始类型。
3:不能创建参数化类型的数组
public static void main(String[] args) {
// TODO Auto-generated method stub
Pair<String> [] array=new Pair<String>[10];
}
运行结果:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Cannot create a generic array of Pair<String>
at com.csu.fanxing.test2.main(test2.java:9)
结果分析:由于array经过虚拟机擦除后,array类型是Pair[],所以假设改数组能够初始化成功,那存储时依然会出现问题。
4:不能实例化类型变量
public class Pair<T> {
private T first;
private T second;
public T getFirst() {
return first;
}
public Pair()
{
first=new T();
second=null;
}
报错:first=new T();Cannot instantiate the type T。无法实例化类型T。所以不能用像new T(),new T[...]等这样的表达式实例化类型变量。
5:泛型类的静态上下文中类型变量无效
public class Singleton <T>{
private static T singleInstance;//错误
public static T getInstance()//错误
{
//dosomething
}
}
编译不通过的主要原因是泛型擦除后,只有Singleton,如果声明一个Singleton和一个Singleton,那么就会出现程序混乱。因为泛型类中的泛型参数的实例化是在定义对象的时候指定的,而静态变量和静态方法不需要使用对象来调用。对象都没有创建,如何确定这个泛型参数是何种类型,所以当然是错误的。
public static<T> T getInstance(T a)//错误
{
//dosomething
}
注意:这个是正确的,因为它是泛型方法,它使用的T是自己在方法中定义的T,而不是泛型类中的T。
6:类型擦除后的冲突
当泛型类型被擦除后,创建条件不能产生冲突。如果在Pair类中添加下面的equals方法:
class Pair<T> {
public boolean equals(T value) {
return null;
}
}
考虑一个Pair。从概念上,它有两个equals方法:
booleanequals(String); //在Pair<T>中定义
boolean equals(Object); //从object中继承
但是,这只是一种错觉。实际上,擦除后方法
boolean equals(T)变成了方法 boolean equals(Object),这与Object.equals方法是冲突的!当然,补救的办法是重新命名引发错误的方法。
7:泛型类型的继承规则
从图可以看出,B与BSub之间是集成关系,但在ArrayList与ArrayList没有任何关系。
但是特别注意:ArrayList与List之间有关系,由于ArrayList实现的是List接口。