泛型类型擦除,如何工作,由来

来源:互联网 发布:如何黑进路由器 知乎 编辑:程序博客网 时间:2024/06/05 21:53
                                                1 泛型由来
    List list = new ArrayList();  
    list.add("CSDN_SEU_Cavin");  
    list.add(100);  
    for (int i = 0; i < list.size(); i++) {  
      String name = (String) list.get(i); //取出Integer时,运行时出现异常  
    System.out.println("name:" + name);  
    }  

本例向list类型集合中加入了一个字符串类型的值和一个Integer类型的值。
(这样合法,因为此时list默认的类型为Object类型)。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他原因,
运行时会出现java.lang.ClassCastException异常。为了解决这个问题,泛型应运而生。

                                     2 泛型只在编译阶段有效(类型擦除)

    AyyayList<String> a = new ArrayList<String>();  
    ArrayList b = new ArrayList();  
    Class c1 = a.getClass();  
    Class c2 = b.getClass();  
    System.out.println(a == b); //true  

上面程序的输出结果为true。所有反射的操作都是在运行时的,既然为true,就证明了编译之后,
程序会采取去泛型化的措施,也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,
并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,成功编译过后的class文件中是不包含任何泛型信息的。
泛型信息不会进入到运行时阶段

                                   3通配符

为了引出通配符的概念,先看如下代码:

  1. List<Integer> ex_int= new ArrayList<Integer>();    
  2. List<Number> ex_num = ex_int; //非法的  报错

上述第2行会出现编译错误,因为Integer虽然是Number的子类,但List<Integer>不是List<Number>的子类型

假定第2行代码没有问题,那么我们可以使用语句ex_num.add(newDouble())在一个List中装入了各种不同类型的子类,这显然是不可以的,因为我们在取出List中的对象时,就分不清楚到底该转型为Integer还是Double了。

 因此,我们需要一个在逻辑上可以用来同时表示为List<Integer>和List<Number>的父类的一个引用类型,类型通配符应运而生。在本例中表示为List<?>即可。下面这个例子也说明了这一点,注释已经写的很清楚了。

  1. public static void main(String[] args) {  
  2.     FX<Number> ex_num = new FX<Number>(100);  
  3.     FX<Integer> ex_int = new FX<Integer>(200);  
  4.     getData(ex_num);  
  5.     getData(ex_int);//编译错误  
  6. }  
  7.   
  8. public static void getData(FX<Number> temp) { //此行若把Number换为“?”编译通过  
  9.     //do something...  
  10. }  
  11.       
  12. public static class FX<T> {  
  13.     private T ob;   
  14.     public FX(T ob) {  
  15.         this.ob = ob;  
  16.     }  
  17. }



                                            4.Java的泛型是如何工作的 ? 什么是类型擦除 ?

Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类型在编译后都会被清除掉

面试题:什么是泛型?泛型的优点?jdk各版本之间的区别?

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
  Java语言引入泛型的好处是安全简单。
  在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,
  而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。
  对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

 
  泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
 
 

 详细讲解 http://www.cnblogs.com/lzq198754/p/5780426.html


原创粉丝点击