泛型的本质是参数化类型或者参数化多态和应用,即可以操作的数据类型指定为方法签名中的一种特殊参数。
JAVA选择的泛型实现方式叫做“类型擦除式泛型”。具体来说就是泛型只在源码中存在,在编译后的字节码文件里,全部泛型都被替换为了原来的裸类型,并且在相应的地方插入了强制转型的代码。
可以结合下面这段代码来理解。
public void test1(){
ArrayList<String> ilist = new ArrayList<>();
ArrayList list;//泛型擦除
list = ilist;
ilist.add("1");
String s = (String)list.get(0);//类型强转
}
也就是说在运行期,JAVA语言中,ArrayList<Integer>和ArrayList<String>其实是同一个类型。这同样带来了一个问题,在运行时无法对泛型进行实例判断,也不能利用泛型类型创建对象或者数组。
public class A<T>{
boolean b = T instanceof Object;//错误
T t = new T();//错误
T[] arr = new T[10];//错误
}
需要特别说明的是,int,long等基本类型无法与Object之间强转,因此只能用Integer,Long等包装类型来实现与Object类之间的强转,这也就是为什么泛型中没有<int>,<long>这种写法的原因。包装类和基本类型之间通过自动拆装箱来达到类型的转换。