当前位置: 首页 > 面试题库 >

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

卫弘图
2023-03-14
问题内容

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

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

我得到了 compilation error

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

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

我可以看到,在很多情况下,这两种方法的html" target="_blank">逻辑非常相似,可以用一个方法代替

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 )方法。但是,当然,编译器需要解析一个方法。为了消除这种歧义,不允许类具有多个等效的方法-即,擦除后具有相同参数类型的多个方法。

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



 类似资料:
  • 如何在不更改方法名称的情况下摆脱以下错误: 我的方法:

  • 我有以下代码,但它不起作用:出现。 我还有这个代码: 这是可行的。在第一种情况下,是,就像在第二种情况下是。那么为什么第一种情况会导致错误,而第二种情况会成功编译? 编辑:我应该怎么做才能实现方法重载,而不引发错误?

  • 我第一次在Java中使用泛型,我遇到了一个无法克服的问题:为什么这样编译: 但这并不: 我得到了这个错误:两种方法有相同的擦除。 如果这是一个愚蠢的问题,我很抱歉,但我不明白为什么有界类型参数声明中的接口顺序似乎很重要。事实上,我不认为是顺序导致了错误,但我不明白是什么导致了错误。 我正在读Oracle的文档,它说我必须把类作为第一个参数,但是Aa,Bb和Cc都是接口。对我的英语也感到抱歉。

  • 在JLS 8第8.4.8.1节中,有一条声明: 在某些参数化下,泛型超类C中的具体方法可以与该类中的抽象方法具有相同的签名。在这种情况下,具体方法是继承的,而抽象方法不是。然后应将继承的方法视为覆盖其来自C的抽象对等体。 有人能为泛型类提供这种参数化的例子吗?我不能。

  • 问题内容: 在Bruce Eckel的“ Thinking In Java,第四版”的第428页(有关类型信息的章节)中,具有以下示例: 也许我有点累,但是我看不到add()方法中对add()的调用是如何工作的。我一直认为它应该有一个引用,或者是一个静态方法(并且我在ArrayList或List中找不到静态add())。我想念什么? 我只是为自己测试,发现这可行: 问题答案: Java为这样的方法

  • 问题内容: 以下代码可以正常工作。在两个不同的结构上操作并打印该结构的字段的两种方法: 在控制台中显示所需的输出: 现在 ,如果我以以下方式更改方法签名,则会出现编译错误。我只是将方法的接收者移动到方法的参数: 我什至无法编译程序: 问 :为什么 当 方法具有相同的名称和Arity 时 ,我可以在接收器中互换结构类型,而不能在参数中互换结构类型? 问题答案: 因为Go不支持在其参数类型上重载用户定