Lets break this down into parts:
<T extends Comparable<? super T>>
This defines the generic bounds of T
- it can represent any type that is Comparable
- either because T
is Comparable
or because some parent class is. Since that parent class (call it P
) likely implements Comparable<P>
rather than Comparable<T>
it's necessary to use super
here. It sounds like you know this already.
T
This is the return type of the method, and can often be specified by the calling context (for instance when you assign the result to a variable). We'll come back to this.
Collection<? extends T>
This allows you to pass in a Collection
of T
s or any subtype of T
(call it S
). If you just specified Collection<T>
you'd only be able to pass Collection<T>
objects and not Collection<S>
objects.
Putting them all together this lets callers do something like:
// notice that max() returns a C, but is assignable to a B
B b = max(new ArrayList<C>());
Where A
, B
, and C
are:
A implements Comparable<A>
B extends A
C extends B
It turns out, since your method returns a T
directly, that the Collection<? extends T>
doesn't really matter because you can always assign a child type (C
) to a parent type (B
). But if we tweak the method signature slightly to return a type using T
as a generic this doesn't work:
public static <T extends Comparable<? super T>> Collection<T>
collect(Collection<T> collection)
Notice we're now returning a Collection<T>
- now the ? extends
becomes important - this doesn't compile:
Collection<B> b = collect(new ArrayList<C>());
Whereas if you change the parameter to Collection<? extends T>
you loosen the bounds; the return type doesn't have to be the same as the parameter type. You can pass in a Collection<C>
but because the caller makes T
mean B
(since that's the type being expected as the return type) C
now extends T
, rather than is T
.
So in short, for your method I don't believe you need the ? extends T
, but in some cases you do. More generally if you intend to support subtypes in your generics it's a good idea to do so explicitly, even if it's not strictly necessary.