Take a look at the next code:
ArrayList<? extends Object> list = new ArrayList<Object>();
list.add(new Object());
It does not compile. The question is why?
Take a look at the next code:
ArrayList<? extends Object> list = new ArrayList<Object>();
list.add(new Object());
It does not compile. The question is why?
ArrayList<? extends Object>
is the same as just
ArrayList<?>
and you can assign any ArrayList to a variable of this type. For example,
ArrayList<? extends Object> list = new ArrayList<String>();
is legal. Clearly, the language semantics will not let you add an Object to such a list. In fact, they won't let you add anything at all to it, except null, or something which you directly retrieved from the list.
As noted by Lukas in the comment, it is far from trivial to even add the list's own item back to it: you need a helper method to capture the wildcard into a named type.
public static void main(String[] args) {
ArrayList<? extends Object> list = new ArrayList<String>();
addOwn(list);
}
static <T> void addOwn(List<T> l) { l.add(l.get(0)); }
I think the reason is because Generic types are not polymorphic. When you use wildcards ? with extends you cant add anything in the collection except null.
Here is an example to what will happen if that is allowed:
Class Car{
}
class A extends Car {
}
class B extends Car{
}
Now you have List<? extends Car>
public void someMethod(List<? extends Car> list){
list.add(new A()); //this is not valid
}
Also you may invoke the method like this:
List<B> someList = new Array:list<B>();
somemethod(someList);
The problem is that Foo extends Object does not mean Collection<Foo> can be treated as a subtype of Collection<Object>. This is simply because the former class does not permit you to do everything the latter does; for instance, you cannot add an Object to a Collection<Foo>. Using generics instead of some concrete class Foo doesn't change this.