为什么在同一个类中有以下两个方法是不合法的?

class Test{
   void add(Set<Integer> ii){}
   void add(Set<String> ss){}
}

我得到编译错误

方法add(Set)与类型Test中的另一个方法具有相同的擦除添加(Set)。

虽然我可以绕过它,但我想知道为什么javac不喜欢这样。

我可以看到,在许多情况下,这两个方法的逻辑非常相似,可以用一个方法来代替

public void add(Set<?> set){}

方法,但情况并非总是如此。

如果你想有两个接受这些参数的构造函数,这是非常烦人的,因为你不能只改变其中一个构造函数的名字。


当前回答

有可能编译器在java字节代码中将Set(Integer)转换为Set(Object)。如果是这种情况,Set(Integer)将仅在编译阶段用于语法检查。

其他回答

这是因为Java泛型是用类型擦除实现的。

在编译时,你的方法会被翻译成这样:

方法解析发生在编译时,不考虑类型参数。(见埃里克森的回答)

void add(Set ii);
void add(Set ss);

这两个方法具有相同的签名,但没有类型参数,因此出现了错误。

定义一个没有void add(Set ii){}类型的方法

您可以根据自己的选择在调用方法时提到类型。它适用于任何类型的集合。

有可能编译器在java字节代码中将Set(Integer)转换为Set(Object)。如果是这种情况,Set(Integer)将仅在编译阶段用于语法检查。

在这种情况下可以使用这种结构:

class Test{
   void add(Integer ... ii){}
   void add(String ... ss){}
}

内部方法可以创建目标集合

void add(Integer ... values){
   this.values = Arrays.asList(values);
}

Java泛型使用类型擦除。尖括号中的位(<Integer>和<String>)被移除,因此您最终会得到两个具有相同签名的方法(您在错误中看到的add(Set))。这是不允许的,因为运行时不知道在每种情况下使用哪个。

如果Java有了具体化的泛型,那么您就可以这样做,但现在可能不太可能。