方法与类型中的另一种方法具有相同的擦除

为什么在同一个班级中使用这两种方法是不合法的?

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

我收到compilation error

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

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

我可以看到,在很多情况下,这两种方法的逻辑非常相似,可以用一个单一的方法取代

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

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

如果你想让两个constructors接受这些参数,这是非常烦人的,因为那样你就不能只改变一个constructors的名字。


此规则旨在避免使用原始类型的遗留代码中的冲突。

这里有一个为什么不允许的例子,来自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>)方法。 但是,当然,编译器需要解决一个方法。 为了消除这种不明确性,类不允许有多个与override等效的方法 - 也就是说,擦除后具有相同参数类型的多个方法。

关键是这是一种语言规则,旨在保持与使用原始类型的旧代码的兼容性。 这不是擦除类型参数所要求的限制; 因为方法解析发生在编译时,所以将通用类型添加到方法标识符就足够了。


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

如果Java获得了泛化的泛型,那么你可以做到这一点,但现在可能不太可能。


这是因为Java泛型是通过Type Erasure实现的。

你的方法在编译时会被翻译成如下形式:

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

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

两种方法都具有相同的签名而没有类型参数,因此是错误的。

链接地址: http://www.djcxy.com/p/73417.html

上一篇: Method has the same erasure as another method in type

下一篇: when and what happens