Java 泛型 - 方法重写

2022-09-02 10:28:48

我有一对类A和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){}
}

我这里有两个问题。
[q1] 如果我这么说,case2 是 case1 的运行时表示形式(在类型擦除之后),我说得对吗?

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

有人请对此有所了解。提前致谢。


答案 1

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

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

    void method(Integer i){}
}

您将在java文档中获得有关类型擦除的完整答案。


答案 2

在 Java 中(从版本 5 开始),被覆盖方法的返回类型必须是协变的,被覆盖方法的参数必须是逆变的。

这意味着重写类在返回的内容方面可以更具体,在接收的内容方面可以接受得更多。

在第二个示例中,假设该类型的变量具有 作为值的实例。ClassAClassB

 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) {...}
}

是有效的,因为 仍然满足 由 定义的协定。ClassDClassC


推荐