该规则旨在避免仍使用原始类型的旧代码中的冲突。
这是从JLS得出的为什么不允许这样做的说明。假设在将泛型引入Java之前,我编写了一些如下代码:
class CollectionConverter {
List toList(Collection c) {...}
}
您可以像这样扩展我的课程:
class Overrider extends CollectionConverter{
List toList(Collection c) {...}
}
引入泛型之后,我决定更新我的库。
class CollectionConverter {
<T> List<T> toList(Collection<T> c) {...}
}
您还没有准备好进行任何更新,因此您不理会Overrider
课程。为了正确覆盖toList()
方法,语言设计人员认为原始类型对于任何泛型类型都是“重写等效”的。这意味着,尽管您的方法签名在形式上不再与我的超类的签名相同,但您的方法仍会被覆盖。
现在,时间流逝,您决定准备好上课了。但是您花了一点时间,而不是编辑现有的原始toList()
方法,而是添加了一个新方法,如下所示:
class Overrider extends CollectionConverter {
@Override
List toList(Collection c) {...}
@Override
<T> List<T> toList(Collection<T> c) {...}
}
由于原始类型的覆盖等效性,这两种方法都具有有效的形式来覆盖该toList(Collection<T>)
方法。但是,当然,编译器需要解析一个方法。为了消除这种歧义,不允许类具有多个等效的方法-即,擦除后具有相同参数类型的多个方法。
关键是这是一种语言规则,旨在维护使用原始类型与旧代码的兼容性。这不是擦除类型参数所要求的限制;因为方法解析是在编译时发生的,所以将泛型添加到方法标识符中就足够了。