Ссылка на дженерики java хорошая ( jdk site ).
Действительно, @Oli_Charlesworth дал хороший ответ, но, возможно, этот будет более полным.
В Collection<? extends Able>
вы не можете вставить ничего правильного.
Если у вас есть
class A implements Able {...}
и
class B implement Able {...}
Тогда Collection<? extends Able>
- это супер тип обоих:
Collection<A>
Collection<B>
Таким образом, законно написать какое-то утверждение типа
//Code snippet 01
Collection< ? extends Able > list;
Collection<A> listA;
Collection<B> listB;
list = listA;
list = listB;
Это действительно причина, по которой существует подстановочный знак Collection<? extends Able>
.
Но здесь все становится интереснее:
В Collection<A>
вы можете вставлять только объекты A
(включая подклассы). То же самое для Collection<B>
. В обоих случаях вы не можете добавить что-то просто Able
. Например:
//Code snippet 02
listA.add( new A() ); //valid at compile-time
listA.add( new B() ); //not valid at compile-time
listB.add( new B() ); //valid at compile-time
listB.add( new A() ); //not valid at compile-time
Таким образом, если вы сгруппируете то, что мы видели в code snippets 01 & 02
, вы поймете, что компилятору абсолютно невозможно принять такое утверждение, как:
Collection< ? extends Able > list;
list.add( new A() ); //not allowed, will work only if list is List<A>
list.add( new B() ); //not allowed, will work only if list is List<B>
Так что да, супер тип Collection< ? extends Able >
не принимает ничего добавить. Более общие типы предлагают пересечение функциональных возможностей подтипов, и, как таковые, меньше функций этого подтипа. Здесь мы теряем возможность добавлять A
объектов и B
объектов. Эти функции появятся позже в иерархии ... и это даже означает, что мы не можем ничего добавить в суперкласс Collection< ? extends Able >
Дополнительное замечание:
Также обратите внимание, что в Collection<Able>
вы можете добавить все, что вы хотите, как это:
Collection< Able > list;
list.add( new A() ); //valid
list.add( new B() ); //valid
Но Collection<Able>
не является суперклассом Collection<A>
и Collection<B>
. Это будет означать, как и в случае любого отношения наследования, что подклассы могут делать все, что может делать их суперкласс, поскольку наследование является специализацией. Таким образом, это будет означать, что мы можем добавить объекты A и B в оба подкласса Collection<A>
и Collection<B>
, но это не так. Так как это не суперкласс, вы не можете иметь:
Collection<Able> list;
Collection<A> listA;
Collection<B> listB;
list = listA; //not valid because there is no inheritance hierarchy
list = listB; //not valid because there is no inheritance hierarchy
Обратите внимание, что наследование является гиперонимическим отношением (обобщение / специализация), а коллекции определяют меронимическое отношение (контейнер / контейнер). И объединить их формально - головная боль, хотя это довольно легко используется нечеткими существами, которых люди представляют, например, на французском языке: synecdocque . :)