L'ho appena testato, il compito stesso viene compilato. Ciò che cambia è se è effettivamente possibile chiamare predicate.test()
.
Facciamo un passo indietro e utilizzare un segnaposto GenericClass<T>
per la spiegazione. Per gli argomenti tipo, Foo
estende Bar
e Bar
estende Baz
.
Estende: Quando si dichiara una GenericClass<? extends Bar>
, che stai dicendo "Io non so che cosa il suo argomento di tipo generico in realtà è, ma è una sottoclasse di Bar
." L'istanza effettiva avrà sempre un argomento di tipo non jolly, ma in questa parte del codice non si sa quale sia il suo valore. Considerare ora cosa significa per le invocazioni dei metodi.
Sai che cosa hai effettivamente ottenuto è uno GenericClass<Foo>
o uno GenericClass<Bar>
. Considera un metodo che restituisce T
. Nel primo caso, il suo tipo di reso è Foo
. Nel secondo, Bar
. In entrambi i casi, si tratta di un sottotipo di Bar
ed è sicuro da assegnare a una variabile Bar
.
Considerare un metodo che ha un parametro T
. Se si tratta di un GenericClass<Foo>
, passarlo a Bar
è un errore - Bar
non è un sottotipo di Foo
.
Quindi, con un limite superiore è possibile utilizzare valori di ritorno generici, ma non parametri di metodo generici.
Super: Quando si dichiara una GenericClass<? super Bar>
, si sta dicendo "Io non so che cosa il suo argomento di tipo generico in realtà, ma è una superclasse di Bar
." Considerare ora cosa significa per le invocazioni dei metodi.
Sai che cosa hai effettivamente ottenuto è uno GenericClass<Bar>
o uno GenericClass<Baz>
. Considera un metodo che restituisce T
. Nel primo caso, restituisce Bar
. In quest'ultimo, Baz
. Se restituisce un valore Baz
, assegnare un valore a una variabile Bar
è un errore. Non sai quale sia, quindi non puoi assolutamente assumere nulla qui.
Considerare un metodo che ha un parametro T
. Se si tratta di un GenericClass<Bar>
, passarlo a Bar
è legale. Se si tratta di un numero GenericClass<Baz>
, passarlo a Bar
è ancora legale perché Bar
è un sottotipo di Baz
.
Quindi, con un limite inferiore è possibile utilizzare parametri di metodo generici, ma non valori di ritorno generici.
In breve: <? extends T>
significa che è possibile utilizzare valori di ritorno generici ma non parametri. <? super T>
significa che è possibile utilizzare parametri generici ma non restituire valori. Predicate.test()
ha un parametro generico, quindi è necessario super
.
Un'altra cosa da considerare: i limiti indicati da un carattere jolly riguardano l'argomento di tipo effettivo dell'oggetto. Le loro conseguenze sui tipi che è possibile utilizzare conoggetto sono l'opposto. Un carattere jolly con limite superiore (extends
) è un limite inferiore per i tipi di variabili a cui è possibile assegnare valori di ritorno. Un carattere jolly con limite inferiore (super
) è un limite superiore dei tipi che è possibile passare come parametri. predicate.test(new Object())
non verrà compilato poiché, con un limite inferiore di String
, accetta solo sottoclassi di String
.
Anche 'extends' compila -' Predicato estende String> predicate = s -> s.startsWith ("g") '- sebbene, non possiamo alimentare un' String' a questo predicato :) vedi anche il mio [articolo] (http://bayou.io/draft/ Capturing_Wildcards.html) su caratteri jolly – ZhongYu
http://stackoverflow.com/questions/33085151/bad-return-type-in-lambda-expression/33085893#33085893 – ZhongYu
'Predicato super String> 'does * not * implica che è possibile passare' Object' ad esso (e provare così creerà un errore del compilatore). La firma 'Predicato super String> 'implica semplicemente che * potrebbe * essere un' Predicato