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.
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.
您不能覆盖声明为的方法
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);
这在一般理论基础上和由于 Java 泛型的特殊性都是不可能的。
一般原则是覆盖方法必须可以替代基类方法。例如,子类方法可以使用更宽的访问修饰符,但不能使用更窄的访问修饰符。在你的情况下,
void say(List<Number> list)
比
void say(List<? extends Number> list)
所以这显然违反了可替代性原则。
一个实际的障碍是:覆盖是关于运行时多态性,而泛型是关于编译时多态性,并且实例的类型参数甚至对方法分派机制不可用。