универсальные методы и подстановочные знаки - PullRequest
3 голосов
/ 18 марта 2012

В чем различия между следующими тремя сигнатурами?

static <T> void foo(List<T>,           Comparator<? super T>);
static <T> void bar(List<? extends T>, Comparator<T>        );
static <T> void baz(List<? extends T>, Comparator<? super T>);

Я знаю, что extends и super означают в общих чертах.У меня вопрос, есть ли разница между foo, bar и baz.Должен ли я сделать один из параметров инвариантным, а другой - вариант в соответствующем направлении, или мне следует сделать оба варианта вариантными?Это имеет значение?

Ответы [ 3 ]

5 голосов
/ 18 марта 2012

PECS - Производитель расширяет, потребитель супер.

Чтобы объяснить это "правило":

  • extends означает, что обобщенный объект создает элементы типа.Когда это коллекция, это означает, что вы можете только брать элементы из коллекции, но не помещать их в нее. Компаратор
  • super означает, что объект потребляет объекты выбранного типа.Таким образом, вы можете добавить в коллекцию, но не читать из нее.
  • Отсутствие расширений и супер означает, что вы можете сделать оба для точного указанного типа.1016 * Что касается Comparator, я не думаю, что это имеет какое-либо значение.Обычно это будет <? super T>, потому что вы, компаратор, потребляете объекты, но во всех трех случаях вы можете безопасно вызывать Collections.sort(list, comparator); (подпись которого <? super T>)
2 голосов
/ 18 марта 2012

Единственная разница в том, представляет ли T параметр типа List, Comparator или что-то среднее.

Что касается вызывающего абонента, три сигнатуры метода эквивалентны, т. Е. Всякий раз, когда может использоваться один из них, могут использоваться и другие.

Для реализации метода, вероятно, наиболее удобен foo, поскольку он позволяет изменять список без необходимости дополнительного преобразования захвата, что потребовало бы делегирования вспомогательному методу.

1 голос
/ 18 марта 2012

Я полагаю, что ? extends T означает, что List может быть универсальным для любого типа, производного от T, тогда как List<T> может быть только List из T, а не любым из его производных классов.

...