3

Why can't void say(List< ? extends Number> list) be overridden by void say(List< Number> list).

Name clash occurs when you try to compile.

4

2 回答 2

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

(有关泛型、通配符和类型关系的详细信息,请参阅此问题)。如果编译器确实允许您覆盖您想要的方式,那么以下是可能的:

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);
于 2013-08-12T11:52:47.400 回答
2

这在一般理论基础上和由于 Java 泛型的特殊性都是不可能的。

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

void say(List<Number> list)

void say(List<? extends Number> list) 

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

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

于 2013-08-12T12:03:13.843 回答