2

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!

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
PetrosB
  • 4,134
  • 5
  • 22
  • 21

4 Answers4

4

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.

Adam Vandenberg
  • 19,991
  • 9
  • 54
  • 56
1

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
Community
  • 1
  • 1
missingfaktor
  • 90,905
  • 62
  • 285
  • 365
  • So, the is redundant and it could just be ? – PetrosB Nov 25 '10 at 09:26
  • @Petros: Every class in Java is subclass of `Object`. Hence the `Object` _part_ is redundant. The other constraint - `extends Comparable` - needs to be retained. – missingfaktor Nov 25 '10 at 11:13
  • @missingfactor: Actually I just found out that is not redundant. It says to the compiler that the erasure of T should be Object instead of Comparable. – PetrosB Nov 26 '10 at 08:24
  • Hi, in The Java Programming Language says "The inclusion of "extends Object " might seem redundant, but it changes the erasure of T to be Object rather than Comparable." – PetrosB Nov 26 '10 at 11:49
  • 1
    @Petros: Yes, you are correct. I didn't know about this feature. Thanks so much for pointing out. Learn something new every day! :-) – missingfaktor Nov 26 '10 at 12:08
0

I'll limit the answer to the "cryptic" parts and assume you understand public, static and basic generics like Collections<T>.

1. Collection<? extends 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.

2. Comparable<? super T>

? 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).

3. &

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).

herman
  • 11,740
  • 5
  • 47
  • 58
0

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
AlexR
  • 114,158
  • 16
  • 130
  • 208