为什么void say(List< ? extends Number> list)不能被void say(List< Number> list)覆盖。
当您试图编译时会发生名称冲突。
发布于 2013-08-12 11:52:47
不能覆盖声明为
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);发布于 2013-08-12 12:03:13
这是不可能的,无论是基于一般的理论基础,也由于Java泛型的特殊性。
一般原则是重写方法必须是基类方法的替代方法。例如,子类方法可能使用更宽的访问修饰符,而不是更窄的访问修饰符。在你的情况下
void say(List<Number> list)比
void say(List<? extends Number> list) 这显然违反了可替代性原则。
一个实际的障碍是:重写是关于运行时多态,而泛型是关于编译时多态,实例的类型参数甚至不能用于方法分派机制。
https://stackoverflow.com/questions/18186228
复制相似问题