Comparator for subclassing

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 using it:

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 do a 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 none of these changes seem to be worth the effort for a large code base. Is there any reasonable situation where it crashes downcast()

or chainComparators()

?

+3


source to share


2 answers


This should be safe because it Comparator

is a consumer, which means that instances T

are only passed as arguments and never returned.



As far as I can see your code is good.

+1


source


If you don't want the flagged warning, you can always do it like this:



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);
        }
    };
}

      

+3


source







All Articles