关于泛型的擦除解释

2020-06-29 10:21:54 浏览数 (1)

类型擦除会出现在泛型方法中,程序员通常认为下述的泛型方法

代码语言: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方法,即:

代码语言:javascript复制
public void setTwo(Object two)

这显然是一个不同的方法,因为它有一个不同类型的参数(Object),而不是People

代码语言:javascript复制
Coupling coupling = new Coupling(...);
Couple<People> cp = interval;
cp.setTwo(people);

这里,希望对setTwo的调用具有多态性,并调用最合适的那个方法。由于cp引用Coupling对象,所以应该调用Coupling.setTwo。问题在于类型擦除与多态发生了冲突。要解决这个问题,就需要编译器在Coupling类中生成一个桥方法:

代码语言:javascript复制
public void setTwo(Object second) {
    setTwo((People)second);
}

变量cp已经声明为类型Couple,并且这个类型只有一个简单的方法叫setTwo,即setTwo(Object)。虚拟机用cp引用的对象调用这个方法。这个对象是Coupling类型的,所以会调用Coupling.setTwo(Object)方法。这个方法是合成的桥方法。它会调用Coupling.setTwo(Date),这也正是我们所期望的结果。

0 人点赞