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){}
}

I get the compilation error

Method add(Set) has the same erasure add(Set) as another method in type Test.

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.

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.

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) {...}
}

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.

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) {...}
}

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.

Java相关问答推荐

为什么JFrame paint()多次绘制同一点(或根本不绘制)?

如何将kotlin代码转换为java

我想了解Java中的模块化.编译我的应用程序时,我有一个ResolutionException

为什么一个java函数会返回一个作为参数传递给它的对象?

Java模式匹配记录

对Java中的通配符参数的混淆

第二次按下按钮后,我需要将按钮恢复到其原始状态,以便它可以再次工作

GetChildren().emoveAll()不会删除 node

如何为JavaFX Spring Boot应用程序制作Windows/MacOS/Linux安装程序

如何在一行中使用Dijkstra中的Java Stream

我的Spring Boot测试显示&IlLegalStateException:无法加载某事的ApplicationContext.

在执行流和相关操作时,使用Java泛型为2个方法执行相同的操作,但对象不同

无法播放音频:从资源加载库GStreamer-Lite失败

带有可选部分的Java DateTimeForMatter

Java嵌套流查找任意值

持续时间--为什么在秒为负数的情况下还要做额外的工作?

无限递归Java问题

将基于实例编号的对象列表拆分为新的对象列表

让标签占用JavaFX中HBox的所有可用空间

在数组列表中找到对象后,未从数组中删除对象