如何解释这些带有擦除的奇怪覆盖规则?

How these strange override rules with erasure can be explained?

这里发生了什么以及如何理解它?

class C<T> {
    public T id(T x) {
        return null;
    }
}

class D extends C<String> {
    public Integer id(Integer x) {  // compiles! but T shall be String ???
        return 7;
    }
}

    public static void main(String[] args) {

        System.out.println(new D().id("7")); // null
        System.out.println(new D().id(7));   // 7

    }

顺便说一下,如果我这样声明 D,编译会失败 Name clash: The method id(Object) of type D has the same erasure as id(T) of type C<T> but does not override it:

class D extends C<String> {
    public Object id(Object x) {   // compile error !
        return 7;
    }
}

编译器在检查您的类型参数是否已被正确使用后,会将您的类型参数替换为 Object。所以编译后,你原来的classD

public Object id(Object x)

public Integer id(Integer x)

非常好。

但是,在您的第二个示例中,同一个 class 中有两个版本的 public Object id(Object x)

使用@Override 注解检查该方法是否真的覆盖了另一个方法。

在第一种情况下,您将有 2 个方法,一个需要 String,另一个需要 Integer。

在第二种情况下,您创建了相同的方法,该方法在超类型的类型擦除后已经存在。