optional
optional

Reputation: 3350

Collections.max method type parameters declaration signature <T extends Comparable<? super T>> explanation

In the Java Generics by Naftalin and wadler in chapter 3 comparison and Bounds , it takes the example of Collections.max method as

<T extends Comparable<? super T>> T max(Collection<? extends T> coll)

and

<T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

second signature is in Java api (for backward compatibility).

As per the Get -put principle I do understand the Producer extends and consumer super .

Now this take an example as follows:

abstract class Fruit {
    protected String name;
    protected int size;
    protected Fruit(String name, int size) {
        this.name = name; this.size = size;
    }
    public boolean equals(Object o) {
        if (o instanceof Fruit) {
        Fruit that = (Fruit)o;
        return this.name.equals(that.name) && this.size == that.size;
        } else return false;
    }
    public int hashCode() {
        return name.hashCode()*29 + size;
    }
    protected int compareTo(Fruit that) {
        return this.size < that.size ? -1 :
        this.size == that.size ? 0 : 1 ;
    }

}
class Apple extends Fruit implements Comparable<Apple> {
    public Apple(int size) {
         super("Apple", size); 
    }
public int compareTo(Apple a) { 
    return super.compareTo(a); 
    }
}
class Orange extends Fruit implements Comparable<Orange> {
    public Orange(int size) { 
        super("Orange", size); 
    }
public int compareTo(Orange o) {
         return super.compareTo(o);
     }
}
class Test {
public static void main(String[] args) {
    Apple a1 = new Apple(1); 
    Apple a2 = new Apple(2);
    Orange o3 = new Orange(3); 
    Orange o4 = new Orange(4);
    List<Apple> apples = Arrays.asList(a1,a2);
    assert Collections.max(apples).equals(a2);
    List<Orange> oranges = Arrays.asList(o3,o4);
    assert Collections.max(oranges).equals(o4);
    List<Fruit> mixed = Arrays.<Fruit>asList(a1,o3);
    assert Collections.max(mixed).equals(o3); // compile-time error
    }
}

Now it says :

This example shows why this wildcard is needed. If we want to compare two oranges, we take T in the preceding code to be Orange:

Orange extends Comparable<? super Orange>

And this is true because both of the following hold:

Orange extends Comparable<Fruit> and Fruit super Orange

Without the super wildcard, finding the maximum of a List<Orange> would be illegal, even though finding the maximum of a List<Fruit> is permitted

I do understand everything in this example except the line Without the super wildcard, finding the maximum of a List<Orange> would be illegal

I am finding myself in unclear situation . However I have gone many answers at stackoverflow explaining the Collections.max method signature(and I do understand that signature, might be not completely).

Upvotes: 1

Views: 165

Answers (1)

shmosel
shmosel

Reputation: 50726

You're misquoting the book. The statement was made about the case where Fruit implements Comparable<Fruit>. In such a case, Orange would not be a valid candidate for <T extends Comparable<T>> because Orange doesn't implement Comparable<Orange>. Therefore, you can't pass a List<Orange> as List<T> unless <T extends Comparable<? super T>>, which ensures that one Orange can be compared to another by means of the Fruit superclass.

Upvotes: 3

Related Questions