java 泛型 擦除
示例1:
Class class1= new ArrayList<String>().getClass(); Class class2=new ArrayList<Integer>().getClass(); System. out.println(class1==class2);
输出:true
解释:
ArrayList<String>和ArrayList<Integer>在运行时,事实上是相同的类型。这两种形式都被他们擦除成它们的“原生”类型,即ArrayList。
示例2:
Class class3= new HashMap<String, Long>().getClass(); Class class4=new HashMap<Double, Exception>().getClass(); System. out.println(class3==class4); System. out.println(Arrays.toString(class3.getTypeParameters())); System. out.println(Arrays.toString(class4.getTypeParameters()));
输出:
true
[K, V]
[K, V]
解释:
在泛型代码内部,无法获得任何有关泛型参数类型的信息。
示例3:
1 class HasF{ 2 3 public void f(){ 4 System. out.println("Hasf obj.f()..." ); 5 } 6 7 } 8 9 10 11 class Manipulator<T extends HasF>{ 12 private T obj ; 13 14 public Manipulator(T x){ 15 obj=x; 16 } 17 18 public void manipulate(){ 19 obj.f(); 20 } 21 } 22 23 24 25 public class ErasedType { 26 27 public static void main(String[] args){ 28 HasF hasF= new HasF(); 29 Manipulator<HasF> manipulator= new Manipulator<HasF>(hasF); 30 manipulator.manipulate(); 31 } 32 }
解释:
如果没有extends HasF,将不能调用T obj 的 f() 方法。
泛型参数类型将擦除到它的第一个边界,编译器实际上会把 参数类型T 替换为它的非泛型上届,如:<T extends HasF>被擦除为HasF,<T>被擦除为Object。
示例4
1 class Erased<T>{ 2 T obj; 3 4 public Erased(){ 5 obj= new T();报错 6 } 7 8 public void f(Object object){ 9 boolean result= object instanceof T ;//!!报错 10 } 11 }
运行时,擦书在方法或类内部移除了有关实际类型的信息。
小结:
擦除减少了泛型的泛化性。java这样设计泛型主要是为了兼容之前没有泛型时候的java语言(迁移兼容性)。