Java 类型擦除、覆盖和泛型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/502614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:27:47  来源:igfitidea点击:

Type erasure, overriding and generics

javagenericsoverridingtype-erasure

提问by Henrik Paul

Can someone explain to me why

有人可以向我解释为什么

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

doesn't override

不覆盖

public void fooMethod(Class c)

and gives me the following errors instead:

并给我以下错误:

 - Name clash: The method fooMethod(Class<?>) 
of type SubClass has the same erasure as fooMethod(Class) of 
type SuperClass but  does not override it

 - The method fooMethod(Class<?>) of type 
SubClass must override a superclass method

?

?

Edit:"java -version" says Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b06-284). As for the code snippet, it's already above, pretty much; the above extends the one below.

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

采纳答案by eljenso

The signature of fooMethod(Class<?>)is the same as the signature of fooMethod(Class)after erasure, since the erasure of Class<?>is simply Class(JLS 4.6). Hence, fooMethod(Class)is a subsignature of the fooMethod(Class<?>)but not the opposite (JLS 8.4.2).

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

For overriding with instance methods you need the overriding method to be a subsignature of the overridden method (JLS 8.4.8.1). This is clearly not the case here.

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

Now that we have established the fact that your subclass method doesn't override the superclass method according to the JLS, let's look at the runtime implications when type erasure has occured. We now have two methods that look exactly the 'same' (same name, same parameter types) but do not override each other. If they don't override, they must be both available on the subtype as separate methods, but they have identical runtime signatures: conflict. So Java has to disallow it.

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

Overriding generic parameter types using raw parameter types isallowed because raw types exist just for this reason: they are a convenient mechanism with specific unsound type rules to accommodate interaction with legacy code. So the type system here will decide that the subclass method doesoverride the superclass one, they areidentical after type erasure and we can never have a conflict. As a consequence of this libraries can be generified independently of existing non-generic code.

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

回答by Staale

Because Class<?>is more specific than just Class.

因为Class<?>不仅仅是Class.

For example, foo(Class<List>)can't override foo(Class<Collection>). I forget the term, but types with generics will always be different from those without.

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