Ho letto molte fonti su caratteri jolly e generici Java. Anche se ho visto molte spiegazioni e risposte, nessuna sembra corretta.
La domanda è molto semplice: le wilcard in Java generici aumentano la flessibilità?
La mia comprensione è "No". I caratteri jolly nei generics di Java (wilcards) in realtà riducono la flessibilità.
Quando ho visto per la prima volta e utilizzato il meccanismo dei generici Java, raramente ho mai usato i caratteri jolly. Molto spesso ho visto e utilizzato la forma <T> abc(T xt)
. Un giorno ho ricevuto una domanda di prova su super
e in seguito ho iniziato a esaminare i caratteri jolly più da vicino.
Molte fonti e in particolare: Effective Java 2nd fornisce un esempio come segue per mostrare come i caratteri jolly aumentano la flessibilità.
public class Stack<E> {
...
public void pushAll(List<E> list) {...}
...
}
I libri continuano e dice che dal momento che dovremmo essere in grado di utilizzare List
di qualsiasi cosa che estende E
come argomento a pushAll(List<E> list)
, questo non è abbastanza flessibile. Pertanto, il libro suggerisce di cambiare la firma del metodo in pushAll(List<? extends E> list)
. Ora se E
è Number
allora possiamo anche usare List<Integer>
come argomento per pushAll(List<? extends Number> list)
. E che abbiamo aumentato la flessibilità (dell'API).
La mia comprensione è che l'altra soluzione non è l'uso di caratteri jolly ma l'uso della digitazione normale. In tal caso, se cambiamo la firma del metodo in
public <T extends E> void pushAll(List<T> list)
raggiungeremo la stessa cosa che la versione con caratteri jolly vuole ottenere.
E ora nel corpo del metodo, non solo possiamo leggere da list
, possiamo anche scrivere in esso. Se usiamo la versione con caratteri jolly, non possiamo scrivere in quell'elenco alcun valore diverso da null
. Pertanto, in questa visualizzazione, i caratteri jolly effettivamente diminuiscono la flessibilità, non aumentano.
Tutto sommato, mi sembra che i caratteri jolly siano effettivamente utilizzati per ridurre la flessibilità in modo che <? extends X>
scoraggi le persone dallo scrivere nell'oggetto mentre <? super X>
scoraggia le persone dalla lettura dell'oggetto (provalo e otterrai solo Object
come tipo del valore restituito). Il seguente esempio illustra il caso <? super X>
.
public void popAll(List<? super E> list) {
Object x = list.get(0) // Only get Object as type here, reading is discouraged
}
Possiamo cambiare la firma in public <T extends E> void popAll(List<T> list)
.
Ora possiamo scrivere o leggere come vogliamo. Non ci sono restrizioni.
Quindi riassumendo: tutti gli usi di caratteri jolly possono essere sostituiti dal parametro digitato nel modo <T extends E>
(quindi ci può essere non è necessario per la parola chiave super
). Usando i caratteri jolly, perdiamo la flessibilità nella capacità di leggere e scrivere nell'oggetto. Pertanto, i caratteri jolly diminuiscono la flessibilità.
È quindi vero che i caratteri jolly in Java riducono effettivamente la flessibilità? Altrimenti, in che modo il mio ragionamento è difettoso?
[ La mia domanda è difettosa in quanto manca i casi menzionati da @Doval nel commento sotto la sua risposta. ]