В чем разница между "супер" и "расширяет" в 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, когда я прочитал статью дяди Боба. Я возобновляю здесь, заключение статьи.
Используйте List
Когда вы помещаете объект в список, все, что вас волнует, это то, что объект имеет тип, который совместим с типом, хранящимся в списке. Таким образом, вы хотите, чтобы список принимал тип этого объекта или любой из суперклассов этого объекта.
Используйте List
С другой стороны, когда вы читаете из списка, вы хотите, чтобы тип, который вы читаете, был типом, содержащимся в списке, или производным от этого типа.
Если вы спрашиваете о параметрах типа, то нет <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