I didn't get it for a while. Many of the answers here, and the other questions show specifically when and where certain usages are errors, but not so much why.
This is how I finally got it. If I have a function that adds Number
s to a List
, I might want to add them of type MySuperEfficientNumber
which is my own custom class that implements Number
(but is not a subclass of Integer
). Now the caller might not know anything about MySuperEfficientNumber
, but as long as they know to treat the elements added to the list as nothing more specific than Number
, they'll be fine.
If I declared my method as:
public static void addNumbersToList(List<? extends Number> numbers)
Then the caller could pass in a List<Integer>
. If my method added a MySuperEfficientNumber
to the end of numbers
, then the caller would no longer have a List
of Integer
s and the following code wouldn't work:
List<Integer> numbers = new ArrayList<Integer>();
addNumbersToList(numbers);
// The following would return a MySuperEfficientNumber not an Integer
Integer i = numbers.get(numbers.size()-1)
Obviously this can't work. And the error would be inside the addNumbersToList
method. You'd get something like:
The method add... is not applicable for the arguments (MySuperEfficientNumber)
Because numbers
could be any specific kind of Number
, not necessarily something that MySuperEfficientNumber
is compatible with. If I flipped the declaration around to use super
, the method would compile without error, but the caller's code would fail with:
The method addNumbersToList(List<? super Number>)... is not applicable for the arguments (List<Integer>)
Because my method is saying, "Don't think that your List
can be of anything more specific than Number
. I might add all sorts of weird Number
s to the list, you'll just have to deal with it. If you want to think of them as something even more general than Number
-- like Object
-- that's fine, I guarantee they'll be at least Number
s, but you can treat them more generally if you want."
Whereas extends
is saying, "I don't really care what kind of List
you give me, as long as each element is at least a Number
. It can be any kind of Number
, even your own weird, custom, made-up Number
s. As long as they implement that interface, we're good. I'm not going to be adding anything to your list since I don't know what actual concrete type you're using there."