views:

713

answers:

2

I am trying to implement a generic sort utility method for a List of objects of any class that implements MyInterface. Per Java API (http://java.sun.com/javase/6/docs/api/java/util/Collections.html), Collections.sort() method signature is:

public static <T> void sort(List<T> list, Comparator<? super T> c)

I am not sure if List with a wildcard parameter can substitute a "plain" parametrized List, but I tried:

static void mySort(List<? extends MyInterface> myList, SortCriteria mySortCriteria) {
    Collections.sort(myList, new Comparator<? super MyInterface>() {
        ...
    });
}

and got a compile time error,

The type new Comparator(){} cannot extend or implement Comparator<? super MyInterface>
A supertype may not specify any wildcard.

So, I changed it to:

static void mySort(List<? extends MyInterface> myList, SortCriteria mySortCriteria) {
    Collections.sort(myList, new Comparator<MyInterface>() {
        ...
    });
}

And it compiles and works. Any good explanations?

A: 

You're using contravariance here.

Basically, you need to have a comparator which can compare any two items in the list. If the list is of type T, that means that it has to be able to compare any two items of type T - but if it can compare any two items of some type X where T is a subclass of X, then that's okay too.

To give my favourite example, if you have a comparator which can compare any two shapes by area, then you could clearly use that to compare any two triangles - so it's okay to sort a List<Triangle> using an AreaShapeComparator.

I'm not sure what you mean by "when I tried it" in your last paragraph... if you could give a short but complete example which doesn't work, we can try to explain why.

EDIT: Okay, you can't use ? extends X or ? extends Y within a new expression - you can only use them as part of a declaration, either of a method, a type or a variable. When you construct a new object, you need to specify the exact type.

Jon Skeet
@Eugene: You need to show *exactly* what you tried - not just a single snippet out of a line, but the whole context.
Jon Skeet
I edited the question - I hope it is clearer now. Thanks!
EugeneV
+1  A: 

I do not understand the effect of this constraint on Comparator

The constraint says that the comparator must be able to compare at the least the generic type of the List, or supertypes of it. For example, it would be valid to use a Comaparator<Number> to sort a List<Integer>. If the Comparator is able to compare Numbers, then it is, of course, able to compare Integers.

oxbow_lakes