Si può leggerlo e ripeterlo più e più volte, come è già successo molte volte. In un commento alla tua domanda, Philipp ha già collegato a una domanda su Stackoverflow che tenta di rispondere . Per me, la spiegazione di Zio Bob ha fatto il trucco.
Scrive (accanto a molte altre cose buone):
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 that T
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 that T
is derived from. It is a base class of T
. Clearly if D
is derived from B
then you can put D
instances into a List<B>
. Likewise, since T
derives from <? super T>
, you can put T
instances into a List<? super T>
. Follow? No? Neither did I for awhile. It takes a bit of getting used to.
Che cosa significa alla fine è che la tua ipotesi di poter mettere i super-tipi di Manager
nella tua List<? super Manager>
è sbagliata. Questo non è ciò che si intende qui. La parola chiave super
risolve il problema di non essere in grado di inserire elementi in luoghi generici mentre sei riuscito a ottenere un po 'di out (con extends
).
Immagina due coppie, una che estenda Manager, una che "la superi":
Pair<? extends Manager> subPair = new Pair<Manager>();
Pair<? super Manager> superPair = new Pair<Manager>();
Ciò che puoi mai fare, è inserire un Employee
in uno di questi:
subPair.setFirst(new Employee());
superPair.setFirst(new Employee());
Se vuoi manager, i dipendenti non saranno mai abbastanza. Ed è peggio: non puoi nemmeno inserire un Executive
nel tuo subPair
, anche se Executive extends Manager
. Non compilerà neanche:
subPair.setFirst(new Executive());
Modifica
Perché? Bene, il tuo generico subPair
fa sempre riferimento ad alcuni "espliciti" Pair
, Pair<Manager>
in questo caso. Potrebbe anche essere riferito a un Pair<CoManager>
(con CoManager extends Manager
). Java non conoscerà il tipo esplicito effettivamente utilizzato e quindi non può consentire le inserzioni.
Ma super
viene in soccorso. Con super
puoi inserire Manager e i loro sottotipi in Pair
. Ed è ciò che super
è per: Inserimento.
superPair.setFirst(new Executive());
Modifica: Qual è il motivo per cui funziona? Mentre extends
ti garantisce un tipo un po ' che implementa (o deriva da) Manager
, super
ti garantisce qualsiasi tale tipo. Quindi, mentre con extends
ottieni un tipo specifico con (almeno) l'interfaccia Manager
, con super
puoi inserire qualsiasi tipo con Manager
interfaccia.
E per l'immagine più grande, suggerisco davvero di leggere l'articolo di Uncle Bob.