public void takeThing(ArrayList<? extends Animal> list)
means "do something with a list of any subclass of Animal
".
public <T extends Animal> void takeThing(ArrayList<T> list)
means "do something with a list of some particular subclass (A.K.A. T
) of Animal
".
If I call list.get()
on the first method, all I know about the returned type is that it extends Animal
. On the second method, if I had another instance of List<T>
, I know that whatever type T
is, both lists would accept the same type.
To take it even further, if I say
Animal animal = list.get(0);
I can no longer say
list.add(animal);
even on the very same list, because we don't have a reference to the generic subtype. If however, I declare a List<T>
where <T extends Animal>
, I can now say
T animal = list.get(0);
list.add(animal);
because we know that list
expects elements of type T
.