0

我有两个课程如下

类查询结果:

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)
    {   ...
    }
}

我收到以下错误:

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

我在类似的问题Java generics name conflict下尝试了答案,具有相同的擦除但得到了更多错误。我想我可能会误解某些东西,或者这些答案不适合我的情况。

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

4

2 回答 2

1

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

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

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

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

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

如果需要,您还可以对该变量设置进一步的界限(即,如果列表元素需要是 QueryResult 的子类型,您可以说 <T extends QueryResult>),这将强制 Java 对 List 进行类型检查以及什么类型它可能具有的元素。

对您的原始代码的进一步评论。在新的通用代码中使用原始类型时要非常小心——您将列表作为原始类型返回:List,而没有指定列表的元素类型是什么,即参数化类型:List<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
于 2017-10-20T13:24:47.817 回答
0

根据Java 文档

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

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

  • 被调用的重写实例方法的版本是子类中的版本。
  • 被调用的隐藏静态方法的版本取决于它是从超类调用还是从子类调用
于 2017-07-06T05:15:53.357 回答