Создание объекта Comparator для сортировки универсального списка<? расширяет T> используя Collections.sort()

Я пытаюсь реализовать универсальный метод утилиты сортировки для списка объектов любого класса, который реализует MyInterface. Для API Java ( http://java.sun.com/javase/6/docs/api/java/util/Collections.html) сигнатура метода Collections.sort() имеет вид:

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

Я не уверен, что List с подстановочным параметром может заменить "простой" параметризованный List, но я попытался:

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

и получил ошибку времени компиляции,

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

Итак, я изменил его на:

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

И это компилируется и работает. Есть хорошие объяснения?

2 ответа

Вы используете контравариантность здесь.

По сути, вам нужен компаратор, который может сравнивать любые два элемента в списке. Если список имеет тип Tэто означает, что он должен иметь возможность сравнивать любые два элемента типа T - но если он может сравнивать любые два элемента некоторого типа X, где T является подклассом X, то это тоже нормально.

Чтобы дать мой любимый пример, если у вас есть компаратор, который может сравнивать любые две фигуры по площади, то вы можете четко использовать это для сравнения любых двух треугольников - так что все в порядке, чтобы отсортировать List<Triangle> используя AreaShapeComparator,

Я не уверен, что вы подразумеваете под "когда я попробовал" в вашем последнем абзаце... если бы вы могли привести короткий, но полный пример, который не работает, мы можем попытаться объяснить, почему.

РЕДАКТИРОВАТЬ: Хорошо, вы не можете использовать ? extends X или же ? extends Y в пределах new выражение - вы можете использовать их только как часть объявления, либо метода, типа или переменной. Когда вы создаете новый объект, вам нужно указать точный тип.

Я не понимаю влияние этого ограничения на Comparator

Ограничение говорит, что компаратор должен иметь возможность сравнивать, по крайней мере, общий тип Listили супертипы этого. Например, было бы правильно использовать Comaparator<Number> сортировать List<Integer>, Если Comparator умеет сравнивать Numberс, то это, конечно, в состоянии сравнить Integers.

Другие вопросы по тегам