类型擦除会出现在泛型方法中,程序员通常认为下述的泛型方法
代码语言:javascript复制public static <T extends Comparable> T min(T[] a)
是一个完整的方法族,而擦除类型之后,只剩下一个方法:
代码语言:javascript复制public static Comparable min(Comparable[] a)
这个时候类型参数T已经被擦除了,只留下了限定类型Comparable
。
但是方法的擦除会带来一些问题:
代码语言:javascript复制class Coupling extends Couple<People> {
public void setTwo(People people) {
super.setTwo(people);
}
}
擦除后:
代码语言:javascript复制class Coupling extends Couple {
public void setTwo(People People) {...}
}
这时,问题出现了,存在另一个从Couple
类继承的setTwo
方法,即:
public void setTwo(Object two)
这显然是一个不同的方法,因为它有一个不同类型的参数(Object
),而不是People
。
Coupling coupling = new Coupling(...);
Couple<People> cp = interval;
cp.setTwo(people);
这里,希望对setTwo
的调用具有多态性,并调用最合适的那个方法。由于cp
引用Coupling
对象,所以应该调用Coupling.setTwo
。问题在于类型擦除与多态发生了冲突。要解决这个问题,就需要编译器在Coupling
类中生成一个桥方法:
public void setTwo(Object second) {
setTwo((People)second);
}
变量cp
已经声明为类型Couple
,并且这个类型只有一个简单的方法叫setTwo
,即setTwo(Object)
。虚拟机用cp
引用的对象调用这个方法。这个对象是Coupling
类型的,所以会调用Coupling.setTwo(Object)
方法。这个方法是合成的桥方法。它会调用Coupling.setTwo(Date)
,这也正是我们所期望的结果。