В чем разница между "супер" и "расширяет" в Java Generics

Я пытаюсь изучить дженерики Java. Мне не понятно когда ты будешь использовать <T extends Foo> и когда вы будете использовать <T super Foo>, Что каждая из этих вещей значит о T? Допустим, у меня есть <T extends Comparable> а также <T super Comparable>что каждый из них означает?

Я прочитал несколько учебных пособий на sun.com, но я все еще потерян. Может кто-нибудь проиллюстрировать примерами?

Спасибо!

6 ответов

Решение

См. Эффективное Java, 2-е издание, пункт 28:

PECS

Производитель, клиент, клиент

Если ваш параметр является производителем, он должен быть <? extends T>, если это потребитель, это должно быть <? super T>,

Взгляните на Google Collections, они знают, как им пользоваться, потому что у них есть Bloch;)

Это зависит от того, какой путь от иерархии наследования это позволяет. Предположим, у вас есть класс "Child", который наследуется от "Parent", который наследуется от "Grandparent".

<T extends Parent> принимает либо родитель, либо ребенок, а <T super Parent> принимает либо родитель, либо дедушка.

Существует три типа подстановочных знаков:

  • ? extends Type: Обозначает семейство подтипов типа Type, Это самый полезный шаблон.
  • ? super Type: Обозначает семейство супертипов типа Type,
  • ?: Обозначает набор всех типов или любой.

Для меня лучший ответ пришел от @BSingh, когда я прочитал статью дяди Боба. Я возобновляю здесь, заключение статьи.

Используйте Listsuper Suit> всякий раз, когда вы собираетесь писать в список.

Когда вы помещаете объект в список, все, что вас волнует, это то, что объект имеет тип, который совместим с типом, хранящимся в списке. Таким образом, вы хотите, чтобы список принимал тип этого объекта или любой из суперклассов этого объекта.

Используйте Listextends Suit> всякий раз, когда вы собираетесь читать из списка.

С другой стороны, когда вы читаете из списка, вы хотите, чтобы тип, который вы читаете, был типом, содержащимся в списке, или производным от этого типа.

Если вы спрашиваете о параметрах типа, то нет <T super X> построить в Java. Ограниченный параметр может только extend, но он может распространяться более чем на один тип. Например

public class MyClass< T extends Closeable & Runnable >
{
  // Closeable and Runnable are chosen for demonstration purposes only
}

В этом случае, если вы видите MyClass< ConcreteT > тогда ConcreteT должен быть объявлен как

public class ConcreteT
  implements Closeable, Runnable
{
   ...
}

Для ограниченных подстановочных знаков, прочитайте эту статью. Читайте раздел о принципах get-put. В принципе, super соответствует write семантика и extends соответствует read семантика.

Помните, что PECS - производитель расширяет поддержку потребителей. Кроме того, дядя Боб хорошо обсуждает это в своей серии "Ремесленник". Проверьте http://objectmentor.com/resources/articles/The_Craftsman_44__Brown_Bag_I.pdf

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