此规则旨在避免仍使用原始类型的旧代码中的冲突。
以下是为什么不允许这样做的说明,来自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>)
关键是,这是一个语言规则,旨在使用原始类型保持与旧代码的兼容性。它不是擦除类型参数所要求的限制;由于方法解析发生在编译时,因此将泛型类型添加到方法标识符就足够了。