我们上回,对泛型类,方法,应用有了一个基本的认识,这回我们来说说泛型和虚拟机:
Part1:类型擦除
无论何时定义一个泛型类型,都自动提供了一个相应的原始类型。原始 类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定的变量用Object)
当程序调用泛型方法时,如果擦除返回类型,编译器插入强制类型转换。例如下面的语句:
Pair<Employee> buddies = ...;
Employee buddy = buddies.getFirst();
擦除getFirst的返回类型后将返回Object类型。编译器自动插入Employee的强制类型转换。也就是说,编译器把这个方法调用翻译为两条虚拟机指令:1.对原始方法Pair.getFirst的调用 2.将返回的Object类强制转换为Employee类型 。
同样的,在泛型方法中,也会存在类型擦除。方法:
public static <T extends Comparable> T min(T[] a)
//这是没擦除的状态
public static Comparable min(Comparable[] a)
//这是擦除的状态
注意啊,类型参数T已经没了,而擦除类型之后,只剩下限定类型Comparable
总之,需要记住有关Java泛型转换的事实:
1.虚拟机中没有泛型,只有普通方法。
2.所有的类型参数都用它们的限定类型替换。
3.桥方法被合成来保持多态。
4.为保持类型安全性,必要时插入强制类型转换
Part3,Tip:
不能用基本类型实例化泛型的类型参数
不能用类型参数代替基本类型。因此,没有Pair,只有Pair。当然,其原因是类型擦除,Object中不能存储double值/
运行时类型查询只适用于原始类型
还是类型擦除,虚拟机只认识原始类型。
不能创建参数化类型的数组
还是类型擦除,你创建一个
public<String>[] table = new Pair<String>[10];
//Error
在虚拟机眼中是这样:
Object[] objarry = table;
需要说明的是,不允许创建(new Pair[10])但是声明还是允许的(Pair[])
最后注意下通配符泛型:
泛型Pair类型,它的类型参数是Employee的子类,我们可以这样写:
Pair<?extends Employee>
同样的,如果他的类型参数是Manager的超类,可以这样:
Pair<?super Manager>