Reputation: 185
In practice, is it safe to do the following?
public static <T> Comparator<T> downcast(final Comparator<? super T> orig) {
@SuppressWarnings("unchecked")
Comparator<T> casted = (Comparator<T>) orig;
return casted;
}
Here's a contrived example of its usage:
public static <T> Comparator<T> chainComparators(final Comparator<? super T> a,
final Comparator<? super T> b) {
if (a == null) {
return downcast(b);
}
if (b == null) {
return downcast(a);
}
return new Comparator<T>() {
@Override
public int compare(T o1, T o2) {
int i = a.compare(o1, o2);
if (i == 0) {
i = b.compare(o1, o2);
}
return i;
}
};
}
public static Comparator<Integer> ODD_FIRST_COMPARATOR = new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
boolean isEven1 = (i1.intValue() % 2) == 0;
boolean isEven2 = (i2.intValue() % 2) == 0;
return Boolean.compare(isEven1, isEven2);
}
};
public static Comparator<Number> ABS_NUMBER_COMPARATOR = new Comparator<Number>() {
@Override
public int compare(Number n1, Number n2) {
double d1 = Math.abs(n1.doubleValue());
double d2 = Math.abs(n2.doubleValue());
return Double.compare(d1, d2);
}
};
public static void main(String[] args) {
Comparator<Integer> comp = null;
comp = chainComparators(comp, ODD_FIRST_COMPARATOR);
comp = chainComparators(comp, ABS_NUMBER_COMPARATOR);
List<Integer> list = new ArrayList<Integer>();
list.add(-42);
list.add(-23);
list.add(-15);
list.add(-4);
list.add(8);
list.add(16);
Collections.sort(list, comp);
System.out.println(list); // prints [-15, -23, -4, 8, 16, -42]
}
I know I could make chainComparators()
return Comparator<? super T>
instead of using downcast()
, or I could change all of the code to not use or explicitly check for null Comparators (which also removes the need to use downcast), but neither of these changes seem to be worth the effort for a large codebase. Is there any reasonable situation where either downcast()
or chainComparators()
will fail?
Upvotes: 3
Views: 1607
Reputation: 122429
If you don't want the unchecked warning, you can always do it this way:
public static <T> Comparator<T> downcast(final Comparator<? super T> orig) {
return new Comparator<T>() {
@Override
public int compare(T o1, T o2) {
return orig.compare(o1, o2);
}
};
}
Upvotes: 3
Reputation: 15145
It should be safe, because Comparator
is a consumer, which means that instances of T
are only passed as arguments, and never returned.
As far as I can see, your code is good.
Upvotes: 1