As per Java API spec, the signature of Collections.reverseOrder is
public static
And the example gi
T
is resolved based on the type of a
.
If you look at the signatures for Arrays.sort()
you will see that the one you are calling has a signature of Arrays.sort(T[], Comparator<? super T>)
, so you are in effect supplying a type parameter in the form of the array type you pass in.
EDIT: I made a small mistake here, and assumed that the call to reverseOrder()
could infer the type, but without at least one parameter, no method could actually do that (see the link).
If the call to Collections.reverseOrder()
took a parameter, then the method could infer the type from the call. There is an overloaded version of the method that takes a Comparator<T>
as an argument. We can demonstrate the inference in Eclipse with the following; hover over Collections.reverseOrder()
:
public class CollectionsFun {
public static void main(String[] args) {
String[] strs = new String[] {"foo", "bar", "baz"};
Comparator<String> comp = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
Arrays.sort(strs, Collections.reverseOrder(comp));
System.out.println(strs);
}
}
Because the call to reverseOrder()
in this example takes a typed parameter, the static method can infer the type that needs to be returned. However, when you call the overloaded form of the method that takes no parameter, no type can be inferred, so you get a Comparator<Object>
back instead of a Comparator<String>
. You can see this by hovering over the reverseOrder()
call in the code below:
public class CollectionsFun {
public static void main(String[] args) {
String[] strs = new String[] {"foo", "bar", "baz"};
Arrays.sort(strs, Collections.reverseOrder());
System.out.println(strs);
}
}
As the signature to Arrays.sort()
says it takes a Comparator<? super T>
it matches Comparator<Object>
. So this all compiles without giving you a "raw types" warning anywhere.
Finally, if you want to show how this would work without type inference, you would do the following:
public class CollectionsFun {
public static void main(String[] args) {
String[] strs = new String[] {"foo", "bar", "baz"};
Arrays.sort(strs, Collections.<String>reverseOrder());
System.out.println(strs);
}
}
The type parameter supplied above ensures that the type of the Comparator
that gets returned is Comparator<String>
.
Types in methods calls can be inferred.
Xyz[] a;
Arrays.sort(a, Collections.reverseOrder());
is equivalent to
Xyz[] a;
Arrays.<Xyz>sort(a, Collections.<Xyz>reverseOrder());
From Java SE 7 something similar works for constructors, only you need to use the "diamond 'operator'" (for not very good reasons).
List<Xyz> xyzs = new ArrayList<>();
T
is being resolved to Object
. This passes, since Arrays.sort(T[], Comparator<? super T>)
would accept a Comparator<Object>
, since Object
is a supertype of T
.
Eclipse confirms that Collections.reverseOrder()
is resolved to a Comparator<Object>
in the code
String[] array = new String[10];
Arrays.sort(array, Collections.reverseOrder());
Arrays.sort() knows what kind of Comparator it needs, since T
is specified by the first argument (a
):
public static <T> void sort(T[] a, Comparator<? super T> c)
EDIT:
@Louis Wasserman correctly points out that we only need a Comparator<? super T>
, not a Comparator<T>
. Since Object
is a superclass of any T
, then Comparator<Object>
(the default if no generic parameters are given) is sufficient.