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

Java name clash error, a method has the same erasure as another method

我有两个class如下

class 查询结果:

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

和class案例结果:

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

我收到以下错误:

Name clash: The method sortResults(boolean, List) of type CaseResult has the same erasure as sortResults(boolean, List) of type QueryResult but does not hide it CaseResult.java

我尝试了类似问题 Java generics name clash , has the same erasure 下的答案,但出现了更多错误。我想我可能误解了什么或者这些答案不适合我的情况。

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

根据Java Documentation,

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

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

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

Darshit Chokshi 的回答中包含了错误的原因。 但是,由于尚未发布 solution/alternative,请尝试以下操作:

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

与其覆盖,不如更改 super class 中的原始方法(在您的示例中为 QueryResult),以便它可以处理任何类型的 List 元素。您可以使用通配符捕获来完成此操作:

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

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

如果需要,您还可以进一步限制此变量(即,如果列表元素需要是 QueryResult 的子类型,您可以说 ),这将强制 Java 执行对列表进行类型检查以及它可能包含的元素类型。

对您的原始代码的进一步评论。在新的泛型代码中使用原始类型时要非常小心 - 您将列表作为原始类型返回: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