Обобщения и сортировка в Java - PullRequest
14 голосов
/ 15 января 2010

Предположим, вы пишете статическую функцию в Java для сортировки массива, очень похоже на Arrays.sort(). Проблема с Arrays.sort() состоит в том, что он получает массив Object и выдает ClassCastException, если его элементы не реализуют Comparable.

Итак, вы хотите, чтобы ваша функция получила в качестве аргумента массив подтипа Comparable. Нечто подобное может сработать:

static <T extends Comparable> void sort(T[] array);

Проблема с этой подписью состоит в том, что вы все равно можете передать массив Comparables с целыми числами и строками, например, что приведет к RuntimeException.

Итак, как вы можете создать функцию, которая получит только массив, элементы которого реализуют Comparable и имеют одинаковый тип (например, Integer, String и т. Д.?)

Ответы [ 3 ]

23 голосов
/ 15 января 2010

Использование

static <T extends Comparable<? super T>> sort(T[] array);

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

14 голосов
/ 15 января 2010

Ответ Дирка - лучшее, что вы можете получить, но Google Collections использовали именно так, как вы написали, чтобы избежать ошибки в javac:

Почему вы используете тип <E extends Comparable> в различных API, которые не является "полностью обобщенным"? Разве это не должно быть <E extends Comparable<?>>, <E extends Comparable<E>> или <E extends Comparable<? super E>>?

Последнее предложение является правильным, как объяснено в Джава. Тем не менее, мы будем использовать <E extends Comparable<E>> на методы без параметров, чтобы обойти отвратительную ошибку javac. Это вызовет проблемы при использовании очень необычного типа, такого как java.sql.Timestamp, который сопоставим с супертипом. (Нужно больше объяснений.)

От: http://code.google.com/p/google-collections/wiki/Faq

Теперь вам решать ...

2 голосов
/ 15 января 2010

В мире Java после 1.5 ссылочные массивы - это просто детали реализации низкого уровня. Предпочитаю, коллекции.

Если вас интересуют ссылочные массивы, по какой-то особой причине вы будете знать, что они действительно не уживаются с дженериками. Вы не можете (разумно) иметь массив универсального типа, например Comparable<String>. Это означает, что если бы Arrays.sort было обобщено аналогично Collections.sort, оно было бы чрезмерно ограничено.

Из-за особенностей типизации массивов, если вы хотите чрезмерно ограничивать типы, я думаю, sort можно записать проще, чем Collections.sort, не жертвуя при этом чем-то существенным.

public static <T extends Comparable<T>> sort(T[] array)

Если вам нужна двоичная совместимость с пре-дженериками, вам понадобится небольшой взлом, чтобы вернуться к подписи Object[], аналогично Collections.min.

public static <T extends Object & Comparable<T>> sort(T[] array)
...