Java名称冲突错误,一种方法与另一种方法

时间:2017-07-06 03:27:00

标签: java generics inheritance compiler-errors name-clash

我有两个课程如下

类QueryResult:

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

和类CaseResult:

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

我收到以下错误:

  

名称冲突:类型为sortResults(boolean,List)的方法   CaseResult与sortResults具有相同的擦除(boolean,   List)类型为QueryResult但不隐藏   它CaseResult.java

我在类似问题Java generics name clash , has the same erasure下尝试了答案,但却遇到了更多错误。我想我可能会误解某些东西,或者那些答案不适合我的情况。

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

2 个答案:

答案 0 :(得分:0)

根据Java Documentation

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

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

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

答案 1 :(得分:0)

Darshit Chokshi的答案涵盖了错误的原因。 但是,由于尚未发布解决方案/替代方案,请尝试以下操作:

您尝试以这种方式覆盖sortResults()方法,以便您可以使用不同的元素对列表进行排序。但是,当覆盖时,您需要具有相同的类型签名。签名在您的情况下看起来类似,但由于List中的元素不同 - 编译器实现了List&lt; QueryResult中&GT;和列表&lt; CaseResult&GT;是不同的,但是由于Java中的类型擦除,它不确定应该调用哪个方法 - 即它应该调用超类方法还是子类方法。

而不是覆盖,而是更改超类中的原始方法(在您的情况下,QueryResult),以便它可以处理任何类型的List元素。您可以使用通配符捕获来实现此目的:

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

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

如果需要,你也可以在这个变量上设置更多的边界(即如果list元素需要是QueryResult的子类型,你可以说&lt; T扩展QueryResult&gt;),这将强制Java对List进行类型检查它可能有什么类型的元素。

对原始代码的进一步评论。在新的通用代码中使用原始类型要非常小心 - 您将列表作为原始类型返回:List,而不指定列表的元素类型是什么,即参数化类型:List&lt; SomeActualType取代。这可能会导致许多问题,因此不建议这样做。 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