此规则旨在避免仍然使用原始类型的遗留代码中的冲突。
这是为什么不允许这样做的说明,取自 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()
方法,你add像这样的新方法:
class Overrider extends CollectionConverter {
@Override
List toList(Collection c) {...}
@Override
<T> List<T> toList(Collection<T> c) {...}
}
由于原始类型的重写等效性,这两种方法都采用有效的形式来重写toList(Collection<T>)
方法。但当然,编译器需要解析单个方法。为了消除这种歧义,类不允许有多个重写等效的方法,即擦除后多个方法具有相同的参数类型。
关键是这是一个旨在保持与使用原始类型的旧代码的兼容性的语言规则。它不是擦除类型参数所需的限制;因为方法解析发生在编译时,所以将泛型类型添加到方法标识符就足够了。