Is there a difference between these two common signatures of the "max" function for a collection

Is there a practical difference between these two signatures:

public static <T extends Comparable<? super T>> T max(Collection<T> c) 

      

and

public static <T extends Comparable<T>> T max(Collection<? extends T> c) 

      

I can't think of a single use case where the two are not interchangeable.

Then what is the reason for both? super T and? extends T in the standard max () method in the Java compilations:

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

      

Edit: This question isn't about the difference between <? super T>

and <? extends T>

. The get / put principle is quite clear to me. The question is the difference between these two specific signatures and why the creators of the Java Collections API chose to mix these two signatures for their standard "max" function.

+3


source to share


3 answers


An example where the two are not interchangeable is:

static class A implements Comparable<Object> {
    @Override
    public int compareTo(final Object o) {
        return 0;
    }
}

      

a list with instances A

works on the first max()

and fails on the second max()

:

error: method max2 in class Generics cannot be applied to given types;
    max2(Arrays.asList(new A()));
    ^
required: Collection<? extends T>
found: List<A>
reason: inference variable T has incompatible bounds
  equality constraints: Object
  upper bounds: Comparable<T>
where T is a type-variable:
  T extends Comparable<T> declared in method <T>max2(Collection<? extends T>)

      



another example:

static class A {}
static class B extends A implements Comparable<A>{
    @Override
    public int compareTo(final A o) {
        return 0;
    }
}

      

max()

was designed in such a way to make sure that its signature is not changed and all compiled code depending on max()

(code up to Java 5) returning Object

can work, more information in Converting legacy code to use common files .

+2


source


Taking a simple example

Animal:

class Animal extends Mammal

      

Cat:

class Cat extends Animal

      

Allows you to split the signature.



max(Collection<? extends T> coll)

      

This is because max must accept a list of animals as well as Cat. Now the rest:

<T extends Comparable<? super T>>

      

This covers the case where I have an Animal class signature something like this:

Animal extends Mammal implements Comparable<Mammal>

      

So my comparable object can accept either of its parents and still do a boolean comparison. I know this is not a very practical example, but I hope it makes sense.

+1


source


Then what is the reason for both? super T and? extends T in the standard max () method in the Java compilations:

Just to make the most of the maximum possible operation, given that the operations it will perform on this collection and their elements are just iterator().next

and compareTo

. In other words, it declares the weakest constraints required for its type of arguments, which still allows its code to compile.

0


source







All Articles