36

有人可以向我解释为什么

@Override
public void fooMethod(Class<?> c)

不覆盖

public void fooMethod(Class c)

并给我以下错误:

- 名称冲突:方法 fooMethod(Class<?>)
SubClass 类型的擦除与 fooMethod(Class) 的相同
输入 SuperClass 但不覆盖它

 - 类型的方法 fooMethod(Class<?>)
子类必须覆盖超类方法

?

编辑:java -version”表示 Java(TM) 2 运行时环境,标准版(内部版本 1.5.0_16-b06-284)。至于代码片段,它已经在上面了,差不多了;上面扩展了下面的。

4

2 回答 2

47

的签名与擦除后fooMethod(Class<?>)的签名相同fooMethod(Class),因为 的擦除Class<?>很简单ClassJLS 4.6)。因此,fooMethod(Class)是一个子签名,fooMethod(Class<?>)但不是相反的(JLS 8.4.2)。

对于使用实例方法进行覆盖,您需要将覆盖方法作为被覆盖方法的子签名(JLS 8.4.8.1)。这显然不是这里的情况。

现在我们已经确定了您的子类方法不会根据 JLS 覆盖超类方法这一事实,让我们看看发生类型擦除时的运行时影响。我们现在有两个看起来完全一样的方法(相同的名称,相同的参数类型),但不会相互覆盖。如果它们不覆盖,它们必须在子类型上都作为单独的方法可用,但它们具有相同的运行时签名:冲突。所以Java必须禁止它。

允许使用原始参数类型覆盖泛型参数类型因为原始类型的存在正是出于这个原因:它们是一种方便的机制,具有特定的不健全的类型规则,以适应与遗留代码的交互。所以这里的类型系统将决定子类方法确实覆盖超类方法,它们在类型擦除后相同的,我们永远不会发生冲突。由于这个库可以独立于现有的非泛型代码进行泛型。

于 2009-02-02T10:23:23.067 回答
-3

因为Class<?>比刚才更具体Class

例如,foo(Class<List>)不能覆盖foo(Class<Collection>). 我忘记了这个术语,但是具有泛型的类型总是与没有泛型的类型不同。

于 2009-02-02T09:04:10.950 回答