在重写generics类的方法时的名称冲突
我试图通过以下代码了解我得到的名称冲突错误:
import java.util.*; import javax.swing.*; class Foo { public void doSomething(Number n, Map comps) { } } class Bar extends Foo { public void doSomething(Number n, Map comps) { } }
错误信息:
错误:名称冲突:
Bar
doSomething(Number,Map)
和Foo
中的doSomething(Number,Map)
具有相同的擦除,但都没有覆盖其他
我知道我可以通过从Foo
删除generics类型,或者通过将Bar
声明更改为class Bar extends Foo
来修复它; 我想知道的是为什么在特定情况下会发生此错误,但如果我从每个方法中删除comps
参数就会消失。 我已经完成了关于类型擦除的一些阅读,但在我看来,这两种方法在使用或不使用generics时都应该具有相同的擦除,因此在任何一种情况下都是有效的覆盖。 (请注意,我还没有在任何地方使用generics参数,这就是为什么我很惊讶。)
我知道我之前已经向父类添加了generics类型,但只获得了有关子类的警告,而不是错误。 有谁能解释这个场景?
Luiggi在评论中是对的。 这是原始类型的结果。
类的超类型可以是原始类型。 该类的成员访问被视为正常,并且超类型的成员访问被视为原始类型 。 在类的构造函数中,对super的调用被视为原始类型的方法调用。
这适用于调用超类型方法,但也适用于覆盖超类型方法。
举例来说,以下内容
class Bar extends Foo { public Bar() { doSomething(1, new HashMap()); } }
您会注意到它编译,即使HashMap
不是可分配给Map
。
未从其超类或超接口inheritance的原始类型
C
的构造函数(第8.8节),实例方法(第8.4节,第9.4节)或非静态字段(第8.3节)的类型是对应于的原始类型在与C
对应的generics声明中擦除其类型。
(注意,在我们的例子中C
是Bar
。)
尝试覆盖方法时会发生同样的事情。 当试图覆盖Foo#doSomething(..)
方法时, Bar
类实际上看到它被声明为
public void doSomething(Number n, Map comps) { }
换句话说,类型参数的每次使用都被擦除。 所以试图声明方法
public void doSomething(Number n, Map comps) { }
在子类型Bar
中实际上是尝试重载,而不是覆盖。 由于类型擦除,这会失败。 您可以使用@Override
validation的正确覆盖是
public void doSomething(Number n, Map comps) { }
进一步阅读:
- 什么是原始类型,为什么我们不应该使用它?