Java泛型小结(三)
Java泛型总结(三)?泛型代码和虚拟机1)类型变量的擦除? 虚拟机并没有泛型类型的对象,所有的对象都是普通类,
Java泛型总结(三)
?
泛型代码和虚拟机1)类型变量的擦除? 虚拟机并没有泛型类型的对象,所有的对象都是普通类,即使是我们看到的泛型类型(如Pair<String>),在编译后都成了普通的类型。任何时候,泛型类型都自动对应一个相应的原型(raw type),就是删除类型变量后的泛型类型名。? 如何擦除类型变量呢。对于有限定类型的,如T extends Comparable 的删除T,并替换成限定的类型Comparable?;没有限定类型的则替换成Object。? 注意到,如果有多个限定类型的呢,例如T extends?Serializable?&?Comparable?? 这个时候,将把T替换成Serializable,因为编译器用的是限定类型中的第一个。但是,替换成Serializable,编译器在编译的时候当需要接口Comparable的compareTo方法时又需要进行强制转换,为了不影响效率,应该替换成Comparable比较好。那么,我们应该把Comparable放在前面,即:T extends?Comparable??&?Serializable。? 因此,我们总结出结论:为了提高效率,应该把tagging interfaces(标签接口,就是没有方法的接口)放在限定类型列表的最后。
2)泛型的翻译??当程序调用泛型方法时,如果擦除返回类型,编译器插入强制类型转换。??When you program a call to a generic method, the compiler inserts casts when the?return type has been erased? 接着第一篇中的例子:? ? ? ? Pair<Employee> pair =?
new?Pair<Employee>();??????? Employee?first?= pair.getFirst();?本来getFirst方法返回的类型是T,按照上面所述的类型擦除后返回类型变为Object,编译器又自动插入Employee的强制类型转换,所以直接就得到了Employee类型了。
3)桥方法(bridge method)? 桥方法用来保持多态,解决类型擦除与多态的冲突。? 例如,存在泛型类Pair<T>
public?
class?Pair<T> {
? ? ?private?T?second?;
? ???
public?
void?setSecond(T second) {????????
this.?second?= second;??? }}
自定义类MyDate继承了Pair<Date>
class?MyDate?
extends?Pair<Date> {????@Override????
public?
void?setSecond(Date second) {????????
…… ;??? }}
在进行类型擦除后变成了:
class?MyDate?
extends?Pair { // 去掉了泛型变量Date????@Override????
public?
void?setSecond(Date second) {? ? ? ? …… ;??? }}当调用setSecond方法时:? ? ? ? MyDate myDate =?
new?MyDate();??????? Pair<Date> pair = myDate;??????? pair.setSecond(?
new?Date());这里的pair声明是Pair<Date>类型,并且仅有一个方法setSecond(Object second),但它实际引用的是MyDate对象,那么语句pair.setSecond(?
new?Date());在调用时,实际调用的是MyDate中的setSecond(Object?second)方法,但是我们看到MyDate中并没有定义这个一个方法,而只有setSecond(Date?second)方法。这时,动态和擦除的冲突就出现了。那么,
桥方法就出现了,编译器在编译的时候,为MyDate生成这样的一个方法:public void setSecond(Object second){ setSecond(Date) second; }也就是,对其中的入参second做了强制转换成Date类型了。

?