Pode-se ler e reiterá-lo repetidas vezes - como já foi várias vezes. Em um comentário à sua pergunta, Philipp já vinculado a uma pergunta no Stackoverflow que tenta respondê-la . Para mim, a explicação do Tio Bob resolveu o problema.
Ele escreve (ao lado de muitas outras coisas boas):
A
List<? super Shape>
is a list into which you may add Shapes. Another way to think of this is that the type<? super T>
is an unknown type thatT
can substitute for. You may have to read that several times before you understand it. I certainly did. So here's yet another way to think about it. The type<? super T>
is a type thatT
is derived from. It is a base class ofT
. Clearly ifD
is derived fromB
then you can putD
instances into aList<B>
. Likewise, sinceT
derives from<? super T>
, you can putT
instances into aList<? super T>
. Follow? No? Neither did I for awhile. It takes a bit of getting used to.
O que isso significa, no final, é que sua suposição de que você poderia colocar super-tipos de Manager
em seu List<? super Manager>
está errada. Não é isso que se entende aqui. A palavra-chave super
soluciona o problema de não ser possível inserir itens em locais genéricos enquanto você conseguiu sair (com extends
).
Imagine dois pares, um que estende o gerente, um que "supere":
Pair<? extends Manager> subPair = new Pair<Manager>();
Pair<? super Manager> superPair = new Pair<Manager>();
O que você pode nunca fazer é inserir um Employee
em qualquer um destes:
subPair.setFirst(new Employee());
superPair.setFirst(new Employee());
Se você quiser gerentes, os funcionários nunca serão suficientes. E é pior: você não pode inserir um Executive
no seu subPair
, mesmo que Executive extends Manager
. Não irá compilar:
subPair.setFirst(new Executive());
Editar:
Por que é que? Bem, seu genérico subPair
sempre se refere a alguns "explícitos" Pair
, Pair<Manager>
neste caso. Pode muito bem ter se referido a um Pair<CoManager>
(com CoManager extends Manager
). O Java não saberá o tipo explícito que é realmente usado e, portanto, não poderá permitir inserções.
Mas super
vem para o resgate. Com super
você pode inserir Gerentes e seus subtipos no seu Pair
. E é para isso que o super
é: Inserindo.
superPair.setFirst(new Executive());
Edit: Por que isso funciona? Embora extends
garanta que você algum digite que implementa (ou deriva de) Manager
, super
garante qualquer tal tipo. Então, enquanto com extends
você obtém um tipo específico com (pelo menos) a interface Manager
, com super
você pode inserir qualquer tipo com o Manager
interface.
E para a foto maior, eu realmente sugiro ler o artigo do tio Bob.