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

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

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

Спасибо!

Ответ 1

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

PECS

P roducer e xtends, C onsumer s uper

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

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

Ответ 2

Это зависит от того, какой путь можно использовать в иерархии наследования. Предположим, у вас есть класс "Ребенок", который наследует от "Родитель", который наследуется от "Бабушки и дедушки".

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

Ответ 3

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

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

Ответ 4

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

Использовать список < T супер Костюм > всякий раз, когда вы переходите к пишите в список.

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

Использовать список < T расширяет Костюм > всякий раз, когда вы переходите к читать из списка.

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

Ответ 5

Если вы спрашиваете о параметрах типа, то в Java нет конструкции <T super X>. Ограниченный параметр может быть только 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.