2013-06-04 23 views
6

Qual è la differenza tra List e List<?>? So che non posso aggiungere alcun elemento allo List<?>. Ho un codice:Elenco ed elenco <?> in Java

List<String> myList = new ArrayList<String>(); 
processList(myList); 
processListGeneric(myList); 

public static void processList(List myList) { 
Iterator it = myList.iterator(); 
while(it.hasNext()) 
    System.out.println(it.next()); 
} 

public static void processListGeneric(List<?> myList) { 
    Iterator<?> it = myList.iterator(); 
    while(it.hasNext()) 
     System.out.println(it.next()); 
} 

Il nome dei due metodi non può essere lo stesso, perché provoca compilazione errore di tempo. Quindi c'è qualche differenza in questi due approcci?

+2

Non viene compilato perché i due metodi avrebbero la stessa firma, poiché i generici (<>) vengono utilizzati solo dal compilatore per verificare il tipo in fase di compilazione. – Sebastien

+1

È possibile aggiungere null ad esso. Quindi non dire che non puoi aggiungere nulla :) –

+0

Con 'java.awt.List' usando il secondo metodo, non penso che la tua classe compilerebbe ...;) – Mikaveli

risposta

1

La differenza è che non è possibile aggiungere nulla a uno List<?>, poiché è un elenco di un tipo sconosciuto.

Per esempio, si è impedito dal fare questo:

List<Integer> listOfInt = new ArrayList<Integer>(); 
List<?> list = listOfInt; 
list.add("hello?"); // Compile-time error 

È possibile aggiungere qualsiasi cosa si desidera il tipo di base List in quanto il tipo di voci di elenco non sia selezionata.

6

Entrambi fanno lo stesso, ma nel secondo caso il compilatore viene informato che si desidera veramente un elenco senza limiti di tipi e non si generano avvisi. Se stai lavorando con Java 5 o versioni successive, sei incoraggiato a utilizzare il secondo approccio.

+3

' Elenco 'è * non * lo stesso di 'Lista '. Come indicato dall'OP, non è possibile aggiungere a 'Lista ' s mentre è ovviamente perfettamente possibile aggiungere a 'Lista ' s. Inoltre, se un metodo prende un 'Elenco ' come argomento, è legale passare, ad esempio, un 'Elenco ' ad esso. Un metodo che accetta un 'Elenco ' non accetta un 'Elenco '. – sepp2k

+0

@ sepp2k Rimossa la parte controversa. –

+2

Stai ancora sostenendo che "entrambi fanno lo stesso". La seconda versione del metodo accetterà argomenti che il primo non accetta. Quindi le due versioni del metodo non sono le stesse. – sepp2k

0

Il secondo metodo utilizza i generici (introdotti in Java 5).

Una distinzione importante è la <?> rappresenta un solo tipo, non un oggetto come questo:

List<? extends Object> myList 

Così si potrebbe dire che con il primo metodo (senza la sintassi jolly) è più flessibile, come si' d essere in grado di aggiungere qualsiasi oggetto al tuo elenco. Sebbene, verrà visualizzato un avviso (del compilatore) che la dichiarazione deve essere parametrizzata.

L'uso della sintassi dei caratteri jolly senza limite per l'<?> eviterà l'avviso, ma stai dicendo al compilatore che potrebbe trattarsi di un elenco di qualsiasi tipo, invece di utilizzare effettivamente i generici per applicare la sicurezza del tipo. Siete fortemente incoraggiati ad usare i generici per aiutarvi a rendere sicuro il vostro tipo di applicazione.

Se, ad esempio, si sa che l'elenco dovrebbe sempre e solo contenere oggetti String, dichiara così:

List<String> myList 

Poi si evitano inutili fusione uso dell'operatore instanceof, ecc

Ecco un breve tutorial su farmaci generici in Java, per vostra informazione:

http://javarevisited.blogspot.co.uk/2011/09/generics-java-example-tutorial.html

0

Entrambi si comportano allo stesso modo. Usando la notazione parametrizzata stai semplicemente evitando qualsiasi avviso in Java5 e versioni successive. Non è possibile avere sia la sintassi nello stesso file java perché a causa dell'eliminazione dei caratteri l'unità compilata ha due metodi con la stessa firma nello stesso file di classe e quindi violare le regole della lingua. Ecco cosa otterresti dal compilatore:

Metodo elenco processi (Elenco) ha la stessa cancellazione elenco processi (Elenco) come un altro metodo in tipo ...

1

List<?> (pronuncia "raccolta di sconosciuto") è una raccolta il cui elemento tipo corrisponde a qualsiasi cosa. Si chiama un tipo jolly per ovvi motivi. fare riferimento al seguente codice

List<String> myList = new ArrayList<String>(); 
myList.add("John"); 
String name = myList.get(0); 
System.out.println(name); //print John 
List<?> myListNew = myList; 
myListNew.add("Sam");//Compile time error 
String nameNew = myListNew.get(0);//Compile time error 
Object newName = myListNew.get(0); 
System.out.println(newName);//Prints John 

Dal momento che non sappiamo cosa il tipo di elemento di myListNew rappresenta, non possiamo aggiungere oggetti ad esso. Il metodo add() accetta gli argomenti di tipo E, il tipo di elemento della raccolta. Quando il parametro del tipo attuale è?, Indica un tipo sconosciuto. Qualsiasi parametro che passiamo per aggiungere dovrebbe essere un sottotipo di questo tipo sconosciuto. Dato che non sappiamo di che tipo si tratti, non possiamo passare nulla. La sola eccezione è null, che è un membro di ogni tipo.

D'altra parte, dato un List<?>, possiamo chiamare get() e utilizzare il risultato. Il tipo di risultato è un tipo sconosciuto, ma sappiamo sempre che si tratta di un oggetto. È quindi sicuro assegnare il risultato di get() a una variabile di tipo Object o passarlo come parametro in cui è previsto il tipo Object.

0

Basta scrivere List senza un parametro di tipo è deprecato, ma in caso contrario equivale a scrivere List<Object>. Quindi la domanda diventa "Qual è la differenza tra List<Object> e List<?> e quale dovrei usare?".

Come già sapete, non è possibile aggiungere (qualcosa di diverso null) per un List<?>, quindi se avete bisogno di aggiungere a un elenco, è necessario utilizzare un List<Object> (o un tipo più specifico se del caso, naturalmente). D'altra parte, un metodo che prende uno List<Object> accetta solo List<Object> s e non tutti gli elenchi che contengono una sottoclasse di Object. Cioè, non accetterebbe un List<String>. Se il metodo accetta uno List<?>, accetta qualsiasi tipo di elenco. Quindi, se non è necessario aggiungere all'elenco, è necessario utilizzare List<?> in quanto è più generale.

Problemi correlati