The variable comparator
has type Comparator<? super Integer>
(or Comparator<Integer>
; it doesn't matter for our purposes). The compiler sees that you want the Collections.reverseOrder()
method to return the type Comparator<? super Integer>
, so it infers the T
in the call to Collections.reverseOrder()
that will make it return a Comparator<? super Integer>
. It might, for example, infer T = Integer
, so the Collections.reverseOrder()
call will return a Comparator<Integer>
(or it is also valid to infer T = Object
, so that Collections.reverseOrder()
will return a Comparator<Object>
; it doesn't matter either way). As for how the Collections.reverseOrder()
gets a value of the type Comparator<Integer>
, that's an internal implementation detail of the library.
In the implementation of the library you are looking at, it has a single global comparator instance, ReverseComparator.REVERSE_ORDER
. But how can Collections.reverseOrder()
return this no matter what T
is? For example, it is not possible for something to be Comparator<Integer>
and Comparator<String>
at the same time. So basically, the library is lying. ReverseComparator.REVERSE_ORDER
is declared as some dummy type of comparator (it happens to be Comparator<Comparable<Object>>
, but it doesn't really matter; it could be Comparator<Math>
for all we care), and then inside the Collections.reverseOrder()
method it does an unchecked cast of ReverseComparator.REVERSE_ORDER
into the right type of comparator that it wants to return (Comparator<T>
).
This unchecked cast is theoretically "incorrect" because ReverseComparator
is not actually a Comparator<T>
for any T
other than Comparable<Object>
(and basically nobody ever implements Comparable<Object>
, so it is basically always "incorrect"). However, generics are erased at runtime (that's why the cast is "unchecked" -- it is not possible to check it at runtime), so it won't cause any exceptions as long as using a ReverseComparator
as a Comparator<Integer>
won't lead to any invalid assumptions at runtime. The only thing that a Comparator<Integer>
needs to do is have a method compare()
that takes two Integer
s. ReverseComparator
's compare()
method is able to do that, since ReverseComparator
's compare()
method takes two Comparable
s, and Integer
s are Comparable
s. ReverseComparator
's compare()
method calls the compareTo()
method on the second argument, passing the first argument; that is valid for Integer
s, since Integer
s are comparable to themselves. So this usage is safe, and the lie does not cause any problems.
If I were able to rewrite the reverseOrder()
API from scratch and implement it in a "safe" way, I would probably do something like this:
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return new Comparator<T>() {
public int compare(T c1, T c2) {
return c2.compareTo(c1);
}
};
}
This guarantees that T
is actually comparable to itself, and doesn't do any unchecked casts. One downside is that it needs to create a new Comparator instance for every call to reverseOrder()
. (Perhaps using lambdas instead of anonymous classes could avoid that.)