Problem with <T extends Comparable <? super T >>

I have three classes: 1.class Algorithm having max() to find the maximum value in Collection :

 public class Algorithm { public static <T extends Comparable<T>> T max(Collection<? extends T> coll) { T max = coll.iterator().next(); for (T elm : coll) { if (max.compareTo(elm) < 0) max = elm; } return max; } } 

2.Class Fruit :

 public class Fruit implements Comparable<Fruit> { private String name; private int size; public Fruit(String name, int size) { this.name = name; this.size = size; } public int compareTo(Fruit that) { if (size < that.size) return -1; else if (size == that.size) return 0; else return 1; } } 

3.class Apple Fruit extension:

 public class Apple extends Fruit { public Apple(int size) { super("Apple", size); } } 

Now the question is:

 public class Main { public static void main(String[] args) { Apple a1 = new Apple(10); Apple a2 = new Apple(34); List<Apple> apples = Arrays.<Apple>asList(a1, a2); System.out.println(Collections.max(apples).size); } } 

According to this Java post - Syntax Question: What is it , I should write it like this: public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll) public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll) . But now it works fine. Why? The Apple class does not implement Comparable<Apple> and there is no super .

[UPDATE]
Java Generics and Collections Book says:

Without the super wildcard character, finding the maximum of a List<Apple> would be illegal, although finding the maximum of List<Fruit> is allowed.

+4
source share
3 answers

Suppose we change the max method to this:

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

You cannot get max for List<Apple> because Apple does not implement Comparable<Apple> , it implements Comparable<Fruit> . But you and I know very well that Apple can compare itself with other Fruit , because it has inherited this functionality.

We fix the problem by changing the max declaration to this:

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

This means that we accept any class T such that:

  • T implements Comparable<T> , or ...
  • T implements Comparable<X> for some X such that X is a superclass of T

To find max , we need to be sure that any instance of T can safely accept another instance of T as an argument to its compare method.

In the first scenario, it is obvious that any instance of T can safely accept another instance of T as an argument to its compare(T) method.

In the second scenario, any instance of T can safely accept another instance of T as an argument to its compare(X) method, because all instances of T are also instances of X

This example shows a second scenario where T corresponds to Apple and X corresponds to Fruit .

+5
source

Instead of Algorithm.max , Collections.max(apples) .

Collections.max has a slightly different declaration:

 public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) 
+1
source

Sorry to have returned this, but I think it is important. Does your code stop working properly when it is changed from Collections.max () to Algorithm.max ()? I did a simple test in jdk8 and I don’t understand why it works fine, while according to Java Generics and Collections it should not.

I have an abstract Fruit class (Comparable implementation):

 public abstract class Fruit implements Comparable<Fruit> { private String name; private int size; public Fruit(String name, int size) { this.name = name; this.size = size; } public int compareTo(Fruit that) { if (size < that.size) return -1; else if (size == that.size) return 0; else return 1; } } 

Then I have Apple extending the Fruit class:

 public class Apple extends Fruit { public Apple(String name, int size) { super(name, size); } } 

And finally:

  public class GenericsTest { @Test public void test1() { final Apple a1 = new Apple("apple1", 50); final Apple a2 = new Apple("apple2", 70); final Apple a3 = new Apple("apple3", 34); final List<Apple> apples = Lists.newArrayList(a1, a2, a3); System.out.println(GenericsTest.max(apples).getSize()); } private static <T extends Comparable<T>> T max(Collection<? extends T> coll) { T max = coll.iterator().next(); for (T elm : coll) { if (max.compareTo(elm) < 0) max = elm; } return max; } } 

Does the code work yet? super T is in the signature of the maximum method, and List is of type Apple. According to the quote you quoted, it should not work. It seems I'm puzzled here ...

0
source

All Articles