Can someone please explain this rather cryptic method signature from the Collections
class?
public static <T extends Object & Comparable<? super T>>
T min(Collection<? extends T> coll)
Thank you!
Type "T" is an Object and implements the "Comparable" interface; the min method returns an object of type T and takes a Collection of T as input.
The part of the method signature after static
and before return type is called type constraints. In your case, the type constraints specifies that the type T
should be subclass of Object
and should implement interface Comparable
.
(The Object
part is redundant; and hence the constraint can be written more briefly as <T extends Comparable<? super T>>
).
<? super T>
and <? extends T>
are called variance annotations. Read more about it here.
EDIT: As @Petros said in the comment below, the inclusion of extends Object
might seem redundant, but it changes the erasure of T to be Object
rather than Comparable
.
The following chart [Source] may help understand this better:
Type Parameters Type Erasure
-------------------------------------------------------------
<T> Object
<T extends Number> Number
<T extends Comparable<T>> Comparable
<T extends Cloneable & Comparable<T>> Cloneable
<T extends Object & Comparable<T>> Object
<S, T extends S> Object, Object
I'll limit the answer to the "cryptic" parts and assume you understand public
, static
and basic generics like Collections<T>
.
The ?
is a wildcard, means any (or unknown) type.
The extends
keyword means that the type parameter for the Collection
must extend the given type T
. In general this is used when an object is used as a "producer" of elements of type T
. In this case this is true because for doing comparison elements of type T
are only read from the collection.
The reason for this? This allows for more flexibility than if just Collection<T>
was used. Example: the following works:
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
Number n = Collections.min(integers);
In the above example, T
equals Number
but the collection's type is Integer
, which extends Number
.
?
is again a wildcard.
The super
keyword means that the type parameter for the Comparable
must be a super type of the given type T
. In general this is used when an object is only used as a "consumer" of elements of type T
. In this case this is true because the compareTo
method from Comparable<T>
only takes ("consumes") an argument of type T
but doesn't return it.
The reason for this? This allows for greater flexibility: although any class X
that implements Comparable
will usually implement Comparable<X>
, in theory it could implement Comparable<Y>
, even without Y
being a super type of X
(although that would be weird and not according to the intended use of Comparable
). As long as Y
is a super type of X
, X
is allowed as return type in a call to this method.
The above two points are usually referred to as the PECS principle (Producer Extends, Consumer Super).
This is used to combine multiple types. In this case Object
was added as a first type to make sure the type after erasure is Object
instead of Comparable
, probably for compatibility reasons with libraries compiled with previous java versions that did not have generics (just a guess).
In addition to Adam's description. Parameter T is needed for argument collection: Collection
So, as minimum we need the following method prototype:
public static <T> T min(Collection<? extends T> coll)
But we have to be able to compare the collection element. So, each element must implement Comparable and our prototype becomes more complicated:
public static <T extends Comparable> T min(Collection<? extends T> coll)
But comparable interface itself is parametrized. To avoid compilation warning we have to say:
public static <T extends Comparable<T>> T min(Collection<? extends T> coll)
Due to each class in Java automatically extends Object I really do not understand why did they make this prototype more complicated, i.e. wrote explicitly that T extends Object. Typically generics definitions like
T extends A & B
are used when A and B are interfaces.
I am not sure that my answer helps because probably it asks yet another question. I'd be happy of somebody can explain why return type
<T extends Comparable<T>> T
was not complicated enough and they said
<T extends Object & Comparable<? super T>> T