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.
You cannot override a method declared as
void say(List<? extends Number> list) // A
with
void say(List<Number> list) // B
simply because the types are not equivalent. For example, List<Integer>
matches List<? extends Number>
but not List<Number>
, so
List<Integer> integers = Arrays.<Integer>asList(1, 2, 3);
a.say(integers); // is valid assuming signature A
b.say(integers); // does not compile
(see this question for details about generics, wildcards, and type relationships). If the compiler did allow you to override the way you want to, then the following would be possible:
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);