《Java架构筑基》从Java基础讲起——泛型擦除

  

一。什么是泛型擦除

  

就是指编译器编译带类型说明的集合时会去掉”类型”信息

  

二。泛型擦除案例

  

泛型是提供给javac编译器使用的,限定集合的输入类型,编译器编译带类型说明的集合时会去掉”类型”信息。

  
 <代码>公共类GenericTest {
  公共静态void main (String [] args) {
  新的GenericTest () .testType ();
  }
  
  公共空间testType () {
  ArrayList文物=new ArrayList ();
  ArrayListcollection2=new ArrayList ();
  
  System.out.println (collection1.getClass ()==collection2.getClass ());//两者类类型一样,即字节码一致
  
  System.out.println (collection2.getClass () . getname ());//类均为java.util.ArrayList,并无实际类型参数信息
  }
  } 
  

输出   

 <代码>正确的
  java.util.ArrayList  
  

为何会返回真正的

  
      <李>这是因为不管为泛型的类型形参传入哪一种类型实参,对于Java来说,它们依然被当成同一类处理,在内存中也只占用一块内存空间。从Java泛型这一概念提出的目的来看,其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的类文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。   <李>在静态方法,静态初始化块或者静态变量的声明和初始化中不允许使用类型形参。由于系统中并不会真正生成泛型类,所以instanceof运算符后不能使用泛型类。   
  

使用反射可跳过编译器,往某个泛型集合加入其它类型数据。

  
      <李>只有引用类型才能作为泛型方法的实际参数   <李>例子:李   
  
 <代码>公共类GenericTest {
  公共静态void main (String [] args) {
  交换(新String[]{" 111 ", " 222 "}, 0, 1);//编译通过//交换(新int [] {1,2}, 0, 1);//编译不通过,因为int不是引用类型
  
  交换(新整数[]{1,2},0,1);//编译通过
  }/*交换数组一的第i个和第j个元素*/公共静态& lt; T>无效的交换(T [], int, int j) {
  T temp=[我];
  [我]=[j];
  一个[j]=temp;
  }
  } 
  

但注意基本类型有时可以作为实参,因为有自动装箱和拆箱。

  
      <李>例子(编译通过了):   
  
 <代码>公共类GenericTest {
  公共静态void main (String [] args) {
  新的GenericTest () .testType ();
  int a=biggerOne (3、5);//int和double,取交为数字
  b=biggerOne数量(5.5);//字符串和整数取交为对象
  对象的c=biggerOne (" 1 ", 2);
  }//从x, y中返回y
  公共静态& lt; T>T biggerOne (T x, y) {
  返回y;
  }
  } 
  
      <李>同时,该例还表明,当实参不一致时,T取交集,即第一个共同的父类。   <李>另外,如果用数字b=biggerOne(5.5);改为字符串c=biggerOne(5.5),则编译报错:李   
  
 <代码>错误:(17日,29)java:不兼容的类型:推断类型不符合上限
  推断:java.lang.Number& java.lang.Comparable<?扩展java.lang.Number& java.lang.Comparable< ?在祝辞
  上限:以java . lang . object  

《Java架构筑基》从Java基础讲起——泛型擦除