4

From Programming Languages: Principles and Paradigms By Maurizio Gabbrielli, Simone Martini

The bound mechanism for type variables is fairly sophisticated and flexible. In particular, a type variable can appear in its own bound. We restrict ourselves to a single example of this case, and we refer the reader to the bibliography for a deeper discussion.

The elements of a class are comparable if the class implements the Comparable interface. We want to define a method which, given a list of elements of generic type as its argument, returns the maximum element of this list. What is the signature we can give to this max method? A first attempt is:

public static <T extends Comparable<T>>
T max(List<T> list)

This expresses the fact that the elements of the list must be comparable with elements of the same type. We now try to use max. We have a type Foo which allows us to compare objects:

class Foo implements Comparable<Object>{...}
List<Foo> cf = ....;

We now invoke max(cf): each element in cf (is a Foo and therefore) is comparable with any object, in particular with every Foo. But the compiler signals an error, because Foo does not implement Comparable<Foo>. In reality it is sufficient that Foo is comparable with one of its own supertypes:

public static <T extends Comparable<? super T>>
T max(List<T> list)

Now, under the same conditions as before, Max(cf) is correct because Foo implements Comparable<Object>.

  1. I assume that ? super T means any supertype of T.

    Since Object is a supertype of T, does the following signature of max work?

     public static <T extends Comparable<Object>>
     T max(List<T> list)
    

    If yes, why not use it instead the last one in the quote?

  2. This is an example involving Comparable interface. What is the general problem that we can use the method in the quote to solve?
3

If we had:

public static <T extends Comparable<Object>>
T max(List<T> list)

It would have worked with

class Foo implements Comparable<Object>{...}
List<Foo> cf = ....;

But not with

class Bar implements Comparable<Bar>{...}
List<Bar> cf = ....;

Their first max signature demands that T can be compared with T - therefore it can not work on a List of Foos, because Foos can be compared with Object. Your max signature demands that T can be compared with Object, therefore it can not work on a List of Bars, because Bar can only be compared with another Bar.

Their second max version is needed to work on both List<Foo> and List<Bar>. It says: "give me a list of something that can compare against other objects of it's type, but if it has a wider comparison method, that also accepts other types, that would be OK - as long as it can accept it's own type.".

So, a list of Baz implements Comparable<Foo> is out of the question, because, because a Baz can not be compared against itself(Baz is not a subclass ofFoo`).

Basically, the general problem solved by this method is that something in a generic may work with a subclass/superclass of the generic parameter, because you are only upcast from/to it. You use ? super T/? extends T to encode this in the signature, so that the generic may be used with a wider variety of types.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.