为什么在同一个类中有以下两种方法是不合法的?
class Test{
void add(Set<Integer> ii){}
void add(Set<String> ss){}
}
我得到 编译错误
Method add(Set) has the same erasure add(Set) as another method in type Test.
虽然我可以解决它,但我想知道为什么 javac 不喜欢这个。
我可以看到,在很多情况下,这两种方法的逻辑非常相似,可以用单个方法代替
public void add(Set<?> set){}
方法,但并非总是如此。
如果您想拥有两个接受这些参数的 constructors
,这会更加烦人,因为您不能只更改其中一个 constructors
的名称。
最佳答案
此规则旨在避免仍在使用原始类型的遗留代码中发生冲突。
这是为什么不允许这样做的说明,drawn from the JLS.假设,在泛型被引入 Java 之前,我写了一些这样的代码:
class CollectionConverter {
List toList(Collection c) {...}
}
你扩展我的类(class),像这样:
class Overrider extends CollectionConverter{
List toList(Collection c) {...}
}
在引入泛型之后,我决定更新我的库。
class CollectionConverter {
<T> List<T> toList(Collection<T> c) {...}
}
您还没有准备好进行任何更新,所以请留下您的 Overrider
单独上课。为了正确覆盖 toList()
方法,语言设计者决定原始类型对任何泛型类型都是“覆盖等效的”。这意味着尽管您的方法签名不再正式等于我的父类(super class)的签名,但您的方法仍然会覆盖。
现在,时间过去了,您决定准备更新您的类(class)。但是你搞砸了一点,而不是编辑现有的原始 toList()
方法,你添加一个像这样的新方法:
class Overrider extends CollectionConverter {
@Override
List toList(Collection c) {...}
@Override
<T> List<T> toList(Collection<T> c) {...}
}
由于原始类型的覆盖等效性,这两种方法都以有效的形式覆盖 toList(Collection<T>)
方法。但当然,编译器需要解析单个方法。为了消除这种歧义,类不允许有多个重写等效的方法,即删除后具有相同参数类型的多个方法。
关键是这是一个语言规则,旨在保持与使用原始类型的旧代码的兼容性。这不是删除类型参数所需的限制;因为方法解析发生在编译时,将泛型类型添加到方法标识符就足够了。
关于java - 方法与类型中的另一个方法具有相同的删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1998544/