泛型方法覆盖8

时间:2013-08-12 11:49:32

标签: java generic-programming

为什么void say(List< ? extends Number> list)无法覆盖void say(List< Number> list)

尝试编译时会发生名称冲突。

2 个答案:

答案 0 :(得分:5)

您无法覆盖声明为

的方法
void say(List<? extends Number> list)   // A

void say(List<Number> list)             // B

仅仅是因为类型不相同。例如,List<Integer>匹配List<? extends Number>但不匹配List<Number>,所以

List<Integer> integers = Arrays.<Integer>asList(1, 2, 3);
a.say(integers);  // is valid assuming signature A
b.say(integers);  // does not compile

(有关generics, wildcards, and type relationships)的详细信息,请参阅此问题。如果编译器允许您覆盖您想要的方式,则可以执行以下操作:

class A {
    void say(List<? extends Number> numbers) { }
}

class B extends A {
    void say(List<Number> numbers) { numbers.add(Double.valueOf(1.0)); }
}


List<Integer> onlyIntsPlease = new ArrayList<Integer>();
B b = new B();

// Oops! The list of `Integer` will now contain a `Double`...
b.say(onlyIntsPlease);

答案 1 :(得分:2)

这在一般理论上和由于Java Generics的细节都是不可能的。

一般原则是对于基类方法,重写方法必须是可替换的。例如,子类方法可以使用更宽的访问修饰符,但不能使用更窄的访问修饰符。在你的情况下,

void say(List<Number> list)

更具约束力
void say(List<? extends Number> list) 

所以这显然违反了可替代性原则。

一个实际的障碍是:覆盖是关于运行时多态,而泛型是关于编译时多态,并且实例的类型参数甚至不可用于方法调度机制。