If your takeThing
method needs to add elements to the list
parameter, the wildcard version will not compile.
The interesting case is when you are not adding to the list and both versions seem to compile and work.
In this case, you would write the wildcard version when you want to allow different type of animals in the list (more flexibility) and the parameter version when you require a fixed type of animal in the list: the T type.
For example the java.util.Collection
declares:
interface Collection<E> {
...
public boolean containsAll(Collection<?> c);
...
}
And suppose you have the following code:
Collection<Object> c = Arrays.<Object>asList(1, 2);
Collection<Integer> i = Arrays.<Integer>asList(1, 2, 3);
i.containsAll(c); //compiles and return true as expected
If the java.util.Collection
would be:
interface Collection<E> {
...
public boolean containsAll(Collection<E> c);
...
}
The above test code would not compile and the flexibility of the Collection
API would be reduced.
It worth noting that the latter definition of containsAll
has the advantage of catching more errors at compile time, for example:
Collection<String> c = Arrays.asList("1", "2");
Collection<Integer> i = Arrays.asList(1, 2, 3);
i.containsAll(c); //does not compile, the integer collection can't contain strings
But misses the valid test with a Collection<Object> c = Arrays.<Object>asList(1, 2);