You use wildcards when you don't care about the exact type argument, when they're not important for how the method performs.
Let's take two methods as an example:
The first method shuffles a list of elements. You don't really need to know the type of the elements in order to shuffle them, so you can use a wildcard to indicate this.
The second method declaration is more difficult. To sort a list of items, you *do* need to know something about those items: You need to know how they compare to one another, otherwise you can't sort them. So instead of a
List<?> it needs a
List<T>. So what is
T?
T extends Comparable<? super T>. This looks difficult, but if you give it some thought it's not really. This part just says that the type is comparable to something - it doesn't matter what - that is a super-type of
T.
Let's say you had a default way of comparing two pieces of
fruit, for instance, by size. We also have a special type of fruit, pears:
Now, if we have a
List<Pear> we can submit it to the
sort() method to have them sorted by size. In this case,
T is
Pear, which works because
Pear is comparable to some super type of itself, namely
Fruit.