Создание объекта 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
с, то это, конечно, в состоянии сравнить Integer
s.