M. Reif
M. Reif

Reputation: 866

Understanding use of Generics within the java collection class

After looking into Java's Collection class (OpenJDK 8_update40), I found the following method:

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
    Iterator<? extends T> i = coll.iterator();
     T candidate = i.next();

     while (i.hasNext()) {
         T next = i.next();
         if (next.compareTo(candidate) > 0)
             candidate = next;
     }
     return candidate;
}

I don't fully understand the use of generic types here. As far as I understand has T to be a subtype of Object which also has to implement the Comparable interface which is also parameterized via a generic parameter. The parameter of Comparable states that is have to be some supertype of T. Due to that we have some kind of recursive type definition.

But here is my question: As far as I know every type in Java is a subtype of Object, so why do they specify it within the definition of T?

Upvotes: 4

Views: 101

Answers (3)

emilianogc
emilianogc

Reputation: 930

This is due to covariance vs. contravariance.

As a general rule:

  • If a generic type T is used to return values, then you use <? extends T> as in Iterator
  • If a generic type T is used to accept values, then you use <? super T> as in Comparable

Upvotes: 0

fge
fge

Reputation: 121712

This is for backwards compatibility reasons.

When you use a generic type and this generic type has lower bounds, such as:

<T extends Foo & Bar> void someMethod(T xxx)

then the runtime signature of someMethod will be:

void someMethod(Foo xxx)

(well, OK, the argument name is not there, but you get the picture).

Now, Collections.max() was defined before JDK 5; and its signature was:

public static Object max(Collection coll)

which, in Java 5, could be translated as:

public static Object max(Collection<Object> coll)

The thing is that the return value of max cannot be a Comparable...


Of course, in this case, more difficulties are added:

  • the second lower bound it itself a generic type;
  • moreover Comparable is a "consumer" in the PECS way (hence Comparable<? super T>);
  • the Collection passed as an argument can have any type which is either T or anything extending T, hence ? extends T; we don't care about the actual type, only that the Collection is guaranteed to return something which is at least a T.

This explains the somewhat convoluted signature...

Upvotes: 6

David Herrero
David Herrero

Reputation: 714

Because if you dont use the "T" the collection would only accept instances of Object.

For example String is subtype of Object, but would not compile because the collection would only accept Object instances.

Upvotes: 0

Related Questions