Java 名称冲突错误,一个方法与另一个方法具有相同的擦除



>我有两个类如下

类查询结果:

public class QueryResult
{
...
public static List sortResults(boolean ascending, List<QueryResult> toSort)
{   ...
}
}

和类案例结果:

public class CaseResult extends QueryResult
{
...
public static List sortResults(boolean ascending, List<CaseResult> toSort)
{   ...
}
}

我收到以下错误:

名称冲突:方法排序结果(布尔值,列表)的类型 CaseResult 与 sortResults(布尔值, 列表)类型为查询结果,但不隐藏 它的情况结果.java

我在类似的问题下尝试了答案 Java 泛型名称冲突 ,具有相同的擦除但出现更多错误。我想我可能误解了什么,或者这些答案不适合我的情况。

有人可以提供任何解决方案或解释更多以帮助我理解吗?谢谢大家。

错误的原因在Darshit Chokshi的回答中有所介绍。 但是,由于尚未发布解决方案/替代方案,请尝试以下操作:

您正在尝试以这种方式重写 sortResults() 方法,以便您可以对具有不同元素的列表进行排序。但是,在重写时,您需要具有相同类型的签名。在您的情况下,签名看起来很相似,但由于 List 中的元素不同 - 编译器意识到 List和 List是不同的,但由于 Java 中的类型擦除,不确定它应该调用哪个方法 - 即它应该调用超类方法还是子类方法。

与其重写,不如更改超类中的原始方法(在您的情况下为 QueryResult),以便它可以处理任何类型的 List 元素。您可以使用通配符捕获来完成此操作:

public class QueryResult {
...
public <T> static List<T> sortResults(boolean ascending, List<T> toSort) {   
...
}
}

此方法接收一个列表,并将推断元素类型,将元素类型分配给泛型类型参数 T。每当想要在方法主体中引用元素类型时,现在可以使用泛型类型变量 T,而不是使用元素类型名称(以前是 QueryResult 或 CaseResult)。

如果需要,你也可以在这个变量上设置更多的边界(即,如果列表元素需要是QueryResult的子类型,你可以说),这将强制Java对List进行类型检查以及它可能具有的元素类型。

对您的原始代码的进一步评论。在新的泛型代码中使用原始类型时要非常小心 - 您将列表作为原始类型返回:List,而不指定列表的元素类型,即参数化类型:List。这可能会导致许多问题,因此不建议这样做。Java 创建者在 Java 中保留了这种形式的编码,以便向后兼容泛型之前存在的代码,但强烈建议不要以这种方式为新的编写代码编写代码。

您可以在教科书中阅读有关原始类型与参数化类型以及使用原始类型的陷阱的更多信息,以及有关通配符捕获和边界的更多信息:

Effective Java, by Joshua Bloch
Section: Generics
Item 23: Don't use raw types in new code
Item 28: Use bounded wildcards to increase API flexibility

根据 Java 文档,

如果子类定义了一个与超类中的静态方法具有相同签名的静态方法,则子类中的方法将隐藏超类中的方法。

隐藏静态方法和重写实例方法之间的区别具有重要意义:

  • 调用的重写实例方法的版本是子类中的版本。
  • 调用的隐藏静态方法的版本取决于它是从超类还是从子类调用

相关内容

  • 没有找到相关文章

最新更新