1.关于泛型擦除
public class ErasedType {
public static void main(String[] args) {
Class c1 = new ArrayList<Integer>().getClass();
Class c2 = new ArrayList<String>().getClass();
System.out.println(c1 == c2);
}
}
上面代码的输出结果为:
class Frop {
}
class Fnorkle {
}
class Quark<Q> {
}
class Particle<POOSITION, MOMENTUM> {
}
public class ErasedType {
public static void main(String[] args) {
List<Frop> list = new ArrayList<Frop>();
Map<Frop, Fnorkle> map = new HashMap<Frop, Fnorkle>();
Quark<Fnorkle> quark = new Quark<Fnorkle>();
Particle<Long, Double> particle = new Particle<Long, Double>();
System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
System.out.println(Arrays.toString(quark.getClass().getTypeParameters()));
System.out.println(Arrays.toString(particle.getClass().getTypeParameters()));
}
}
以上代码的输出结果为:
从以上内容可以发现,在泛型代码的内部,无法获得任何有关泛型参数类型的信息。
由第一个例子可以看出在运行时他们是相同的类型。
第二个例子只是看到了占位符的标识符,没有任何有用的信息。
2.擦除的问题
泛型不能用于显式的引用运行时类型的操作之中,例如转型、instanceof以及new。
class Frop<T> {
}
class Cat {
}
public class ErasedType {
public static void main(String[] args) {
Frop<Cat> frop = new Frop<Cat>();
}
}
上述代码中,只是看起来拥有相关参数的类型信息,T被Cat所替换,但是实际上并非如此,它只是一个Object。
3.擦除的补偿
class Building {
}
class House extends Building {
}
public class ErasedType<T> {
Class<T> kind;
public ErasedType(Class<T> kind) {
this.kind = kind;
}
public boolean f(Object obj){
return kind.isInstance(obj);
}
public static void main(String[] args) {
ErasedType<Building> ctt1=new ErasedType<Building>(Building.class);
System.out.println(ctt1.f(new Building()));
System.out.println(ctt1.f(new House()));
ErasedType<House> ctt2=new ErasedType<House>(House.class);
System.out.println(ctt2.f(new Building()));
System.out.println(ctt2.f(new House()));
}
}
有时可以通过引入类型标签对擦除进行补偿,这意味着,有时候需要显式地将类型的Class对象进行传递。以便可以在类型表达式中使用。
4.边界
因为擦除移除了类型信息,但是泛型重用了extends关键字为泛型参数类型上设置限制条件。