La prima firma dice: lista1 è una lista di Es.
La seconda firma indica: elenco è un elenco di istanze di qualche tipo, ma non conosciamo il tipo.
La differenza diventa evidente quando si cerca di modificare il metodo in modo che richiede un secondo argomento, che dovrebbe essere aggiunto all'elenco all'interno del metodo:
import java.util.List;
public class Experiment {
public static <E> void funct1(final List<E> list1, final E something) {
list1.add(something);
}
public static void funct2(final List<?> list, final Object something) {
list.add(something); // does not compile
}
}
Il primo funziona bene. E non puoi cambiare il secondo argomento in qualcosa che verrà effettivamente compilato.
In realtà ho appena trovato una dimostrazione ancora più bello della differenza:
public class Experiment {
public static <E> void funct1(final List<E> list) {
list.add(list.get(0));
}
public static void funct2(final List<?> list) {
list.add(list.get(0)); // !!!!!!!!!!!!!! won't compile !!!!!!!!!
}
}
Sarebbe come il motivo per cui abbiamo bisogno <?>
quando si limita solo ciò che possiamo fare con esso (come ha fatto @Babu_Reddy_H nei commenti) . Vedo i seguenti vantaggi della versione jolly:
Il chiamante deve conoscere di meno circa l'oggetto che passa, ad esempio se ho un Mappa di Liste:. Map<String, List<?>>
posso passare i suoi valori alla funzione, senza specificando il tipo degli elementi della lista. Quindi
Se distribuisco oggetti parametrizzati in questo modo, limito attivamente ciò che le persone sanno di questi oggetti e cosa possono fare con esso (a patto che rimangano lontani da un casting non sicuro).
Questi due hanno senso quando li unisco: List<? extends T>
. Ad esempio, prendere in considerazione un metodo List<T> merge(List<? extends T>, List<? extends T>)
, che unisce i due elenchi di input a un nuovo elenco di risultati. Certo, potresti introdurre altri due parametri di tipo, ma perché vorresti? Sarebbe finita di specificare le cose.
- finalmente jolly può avere limiti inferiori, quindi con le liste si può fare il lavoro
add
metodo, mentre get
non ti dà qualcosa di utile. Ovviamente questo fa scattare la domanda successiva: perché i generici non hanno limiti inferiori?
Per una più approfondita risposta vedere: When to use generic methods and when to use wild-card? e http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203
fonte
2012-06-08 05:07:21
Se String si riferisce a 'java.lang.String', penso che funct2 sia piuttosto ridondante nelle espressioni jolly, poiché' java.lang.String' è una classe finale e non può essere estesa. – nhahtdh
Questo è strano perché tecnicamente non è possibile estendere String dal momento che è una classe finale. –
tuttavia non vi è alcuna restrizione sull'uso della funzione 2: in quanto consente di sottoclassi di String (anche se impossibile) o della classe String stessa ... – ria