相信大家对于泛型都有或多或少的理解,但是泛型擦除这个词可能很少听说过也很少能够用的到。

一、泛型擦除:在java编程思想(第四版)中提到它是解决  java泛型支持向后兼容性和迁移兼容性的唯一可行方案。

简单解释一下这两个特性:

        在我们编写集合时,普遍会用到泛型,例如:

        List<String> list = new ArrayList<String>();

        但是我们也可能这样声明:

        List list = new ArrayList();(下接三)

二、在泛型代码内部,将有关泛型参数的类型信息擦除到第一个边界。如果该参数没有指定边界,那么直接擦除到Object,也就是说,在泛型代码内部,无法获得任何有关泛型参数类型的信息。例如:

Class c1 =  new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println(c1==c2);

在编译时编译器会将new ArrayList中的泛型参数全部擦除掉。也就是说编译器是先将

new ArrayList<String>、new ArrayList<Integer>中的类型参数擦除掉,使其全部变成ArrayList类型,然后才将此类型赋值给c1,c2.所以在下边的比较中,c1和c2的类型是相同的。

三、这时候问题就出现了,拿jdk1.4到jdk1.5这个重大的变更来说(jdk支持了泛型),jdk1.4的类库中是不支持泛型的,但是到了jdk1.5以后,集合类普遍已经支持了使用泛型。那么问题来了,这么巨大的变更,(1).如何保证jdk1.5能够正确的支持jdk1.4时代或者更早的时候出现的代码;(2).又如何能保证在jdk1.5之后开发的代码使用了泛型,但是所用到的类库并没有使用泛型,这个时候在开发时编译器不会报错,并且代码能够正确无误的执行。(3)保证泛型这个概念在jdk1.5以后可以像他们想象的那样能够使用,并且不影响以前的代码。

如下:

/**
  * 研究泛型擦除的内部逻辑
  * @author YR123
  *
  */
 public interface Cachu{    public void get();
     public void set();
 }
 class CachuClass1 implements Cachu{    @Override
     public void get() {
         System.out.println("get");
     }    @Override
     public void set() {
         System.out.println("set");
     }
     public void run(){
         System.out.println("run");
     }
 }
 /**
  * 测试类见Test01
  * @author YR123
  *
  */
  class CachuClass2 implements Cachu{    @Override
     public void get() {
         System.out.println("get");
     }    @Override
     public void set() {
         System.out.println("set");
     }
     /**
      * 泛型方法,因为设置了边界,所以在泛型方法中可以使用Cachu接口中的方法,
      * 如果没有设置边界,则在CachuClass2类中会将a的信息擦除成Object,此时肯定无法调用泛型方法
      * @param a
      */
     public  <A extends Cachu>void post(A a){
         a.get();
         a.set();
         //会报错,让转换成CachuClass1类型
         //a.run();
     }
     /**
      * boundary 边界
      * @param a
      */
     public  <A> void noBoundary(A a){
         //会报错,因为此刻A已经被擦除成Object,编译器在A中找不到get、set方法
         /*a.get();
         a.set();*/
         //此时只有Object类中独有的方法可以正常编译
         a.equals(new Object());
         
     }
 }