方法与类型中的另一个方法具有相同的擦除 [英] Method has the same erasure as another method in type
问题描述
为什么在同一个类中有以下两个方法是不合法的?
Why is it not legal to have the following two methods in the same class?
class Test{
void add(Set<Integer> ii){}
void add(Set<String> ss){}
}
我收到编译错误
方法 add(Set) 与类型 Test 中的另一个方法具有相同的擦除 add(Set).
Method add(Set) has the same erasure add(Set) as another method in type Test.
虽然我可以解决这个问题,但我想知道为什么 javac 不喜欢这个.
while I can work around it, I was wondering why javac doesn't like this.
我可以看到,在很多情况下,这两种方法的逻辑非常相似,可以用一个单独的
I can see that in many cases, the logic of those two methods would be very similar and could be replaced by a single
public void add(Set<?> set){}
方法,但情况并非总是如此.
method, but this is not always the case.
如果你想有两个接受这些参数的 constructors
这会很烦人,因为这样你就不能只改变其中一个 constructors
的名字.>
This is extra annoying if you want to have two constructors
that takes those arguments because then you can't just change the name of one of the constructors
.
推荐答案
此规则旨在避免仍然使用原始类型的遗留代码中的冲突.
This rule is intended to avoid conflicts in legacy code that still uses raw types.
以下说明了为什么不允许这样做,取自 JLS. 假设,在将泛型引入 Java 之前,我写了一些这样的代码:
Here's an illustration of why this was not allowed, drawn from the JLS. Suppose, before generics were introduced to Java, I wrote some code like this:
class CollectionConverter {
List toList(Collection c) {...}
}
你扩展我的类,就像这样:
You extend my class, like this:
class Overrider extends CollectionConverter{
List toList(Collection c) {...}
}
在引入泛型之后,我决定更新我的库.
After the introduction of generics, I decided to update my library.
class CollectionConverter {
<T> List<T> toList(Collection<T> c) {...}
}
您还没有准备好进行任何更新,因此您将 Overrider
类放在一边.为了正确覆盖 toList()
方法,语言设计者决定原始类型与任何泛化类型覆盖等效".这意味着尽管您的方法签名不再正式等同于我的超类的签名,但您的方法仍然会覆盖.
You aren't ready to make any updates, so you leave your Overrider
class alone. In order to correctly override the toList()
method, the language designers decided that a raw type was "override-equivalent" to any generified type. This means that although your method signature is no longer formally equal to my superclass' signature, your method still overrides.
现在,时间过去了,您决定已准备好更新您的课程.但是你搞砸了一点,而不是编辑现有的原始 toList()
方法,你添加一个像这样的新方法:
Now, time passes and you decide you are ready to update your class. But you screw up a little, and instead of editing the existing, raw toList()
method, you add a new method like this:
class Overrider extends CollectionConverter {
@Override
List toList(Collection c) {...}
@Override
<T> List<T> toList(Collection<T> c) {...}
}
由于原始类型的覆盖等效性,这两种方法都是覆盖 toList(Collection
方法的有效形式.但是当然,编译器需要解析单个方法.为了消除这种歧义,类不允许有多个覆盖等效的方法——即擦除后具有相同参数类型的多个方法.
Because of the override equivalence of raw types, both methods are in a valid form to override the toList(Collection<T>)
method. But of course, the compiler needs to resolve a single method. To eliminate this ambiguity, classes are not allowed to have multiple methods that are override-equivalent—that is, multiple methods with the same parameter types after erasure.
关键是这是一种语言规则,旨在保持与使用原始类型的旧代码的兼容性.不是擦除类型参数所要求的限制;因为方法解析发生在编译时,所以向方法标识符添加泛型类型就足够了.
The key is that this is a language rule designed to maintain compatibility with old code using raw types. It is not a limitation required by the erasure of type parameters; because method resolution occurs at compile-time, adding generic types to the method identifier would have been sufficient.
这篇关于方法与类型中的另一个方法具有相同的擦除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!