Java 泛型 - 方法覆盖

Java Generics - Method overriding

我有一对 类 ClassA 和 ClassB,如下所示。
案例 1:

class ClassA<T extends Number>{
    void method(T t){}
}

class ClassB extends ClassA<Integer>{
    @Override
    void method(Integer i){}
}

案例 2:

class ClassA{
    void method(Number t){}
}

class ClassB extends ClassA{
    @Override
    void method(Integer i){}
}

我有两个问题。
[问题一] 我说的对吗,case2 是 case1 的运行时表示(类型擦除后)?

[q2] 如果我对 [q1] 的看法是正确的,那么为什么 case1 被接受为有效的覆盖? (我知道为什么 case2 不是有效的覆盖,因为参数不一样。)

有人请阐明这一点。 提前致谢。

[q1] 的答案是否定的。 编译器将在 ClassB 中生成一个 bridge 方法,该方法实际上会覆盖 method(Number).

class ClassB extends ClassA{
    // bridge method
    void method(Number i){
        method((Integer)i);
    }

    void method(Integer i){}
}

您将在java doc类型擦除中获得完整答案。

ClassB 的实际超类是 ClassA<Integer>。因此其成员函数 method 具有编译时签名:

void method(Integer t){}

你可以通过调用类似

的东西来说服自己
ClassA a = new ClassB();
a.method(1.0);

您应该会看到一个运行时错误。实际上只能这样编译,因为我用的是擦除版的ClassA。事实上,每一个分配给 ClassA<Integer> 以外的泛型类型(例如 ClassA<Number>)将因类型不兼容而失败。

在 Java 中(从版本 5 开始)return 重写方法的类型必须是协变的,并且重写方法的参数必须是逆变的。

这意味着覆盖 class 的内容可以更具体 return 并且可以接受的内容更多。

在您的第二个示例中,想象一个类型为 ClassA 的变量,其中一个 ClassB 的实例作为值。

 ClassA a = new ClassB(); // This is legal, since ClassB is a subclass of ClassA
 a.method(1.0); // This is legal, since ClassA.method accepts Number

不过换一种方式也可以:

public class ClassC { public Number method(Integer i) {...} }
public class ClassD extends ClassC {
   @Override 
   public Integer method(Number n) {...}
}

有效,因为 ClassD 仍然履行 ClassC 定义的合同。