官方文档介绍了泛型擦除: https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

翻译过来就是

  1. 用类型参数的上界或者Object(如果没有上界)替换类型参数,产生的字节码仅包含普通的类,接口和方法
  2. 如有必要,插入强制类型转换以保证类型安全
  3. 生成桥接方法以保留扩展泛型类型中的多态性

以下可以验证运行时的类型擦除和编译的强制类型转换

@Test
public void test() throws Exception {
    List<String> list = new ArrayList<String>();
    // 如果用String.class则报java.lang.NoSuchMethodException,
    // 说明运行时add方法的入参类型是Object,类型擦除
    Method method = list.getClass().getDeclaredMethod("add", Object.class);

    method.invoke(list, new Integer(1));

    Object a = list.get(0);

    // 使用System.out.println(list.get(0)); 导致 
    // java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    // 因为编译器会加入System.out.println((String)list.get(0)),编译器认为println的入参类型是String
    System.out.println(a);// 1

    System.out.println(a.getClass());// java.lang.Integer
}

对于生成桥接方法保留多态性,官方文档有专门介绍,https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html

根据文档,编译器桥接方法保证了继承(或实现)带泛型类(或接口)的类的多态性,注意不是解决了类型转换异常

参考文章:

https://www.ibm.com/developerworks/cn/java/java-language-type-erasure/index.html