覆盖泛型类的方法时的名称冲突



我试图理解使用以下代码得到的名称冲突错误:

import java.util.*;
import javax.swing.*;
class Foo<R extends Number> {
    public void doSomething(Number n, Map<String, JComponent> comps) {
    }
}
class Bar extends Foo {
    public void doSomething(Number n, Map<String, JComponent> comps) {
    }
}

错误信息:

错误:名称冲突:doSomething(Number,Map<String,JComponent>) BarFoo doSomething(Number,Map<String,JComponent>)有相同的 擦除,但两者都不会覆盖另一个

我知道我可以通过从Foo中删除泛型类型或将Bar声明更改为class Bar extends Foo<Integer>来修复它;我想知道的是为什么在特定情况下会发生此错误,但如果我从每个方法中删除comps参数,则会消失。我已经阅读了一些关于类型擦除的内容,但在我看来,这两种方法都应该具有相同的擦除,无论是否具有泛型,因此在任何一种情况下都是有效的覆盖。(请注意,我什至还没有在任何地方使用通用参数,这就是我如此惊讶的原因。

我知道我之前已经向父类添加了泛型类型,但只收到有关子类的警告,而不是错误。谁能解释这种情况?

Luiggi在评论中是正确的。这是原始类型的结果。

类的超类型可以是原始类型。会员访问 类被视为正常类,超类型的成员访问为 与原始类型一样处理。在类的构造函数中,调用 super 被视为对原始类型的方法调用。

这适用于调用超类型方法,也适用于重写超类型方法。

举个例子,下面

class Bar extends Foo {
    public Bar() {
        doSomething(1, new HashMap<Number, String>());
    }
}

您会注意到它会编译,即使HashMap<Number, String>不是可分配给 Map<String, JComponent> 的类型。

构造函数的类型 (§8.8(、实例方法的类型 (§8.4, §9.4( 或 原始类型的非静态字段 (§8.3( C,不是从其继承的 超类或超接口是对应于 在对应于C的通用声明中擦除其类型。

(请注意,在我们的例子中CBar

尝试重写方法时也会发生同样的事情。尝试重写 Foo#doSomething(..) 方法时,Bar类实际上看到它被声明为

public void doSomething(Number n, Map comps) {
}

换句话说,类型参数的每个用法都会被擦除。所以尝试声明方法

public void doSomething(Number n, Map<String, JComponent> comps) {
}

在子类型中,Bar实际上是尝试重载,而不是覆盖。由于类型擦除,这失败了。您可以使用@Override验证的正确覆盖是

public void doSomething(Number n, Map comps) {
}

延伸阅读:

  • 什么是原始类型,为什么我们不应该使用它?

相关内容

  • 没有找到相关文章

最新更新