2009-07-02 7 views
23

Mi sono imbattuto in qualcosa di molto semplice ma estremamente sconcertante oggi. Avevo bisogno di convertire una lista in un array. L'elenco conteneva istanze String. Esempio perfetto di utilizzo di List.toArray(T[]), poiché volevo un'istanza String[]. Tuttavia, non funzionerebbe senza il risultato esplicito del risultato su String[].Comportamenti generici dispari di List.toArray (T [])

Come scenario di test, ho usato il seguente codice:

import java.util.Arrays; 
import java.util.List; 

public class MainClass { 
    public static void main(String args[]) { 
     List l = Arrays.asList("a", "b", "c"); 
     String stuff[] = l.toArray(new String[0]); 
     System.err.println(Arrays.asList(stuff)); 
    } 
} 

, che non può essere compilato. E 'quasi una copia esatta della esempio nel javadoc, ma il compilatore dice quanto segue:

MainClass.java:7: incompatible types 
found : java.lang.Object[] 
required: java.lang.String[] 
    String stuff[] = l.toArray(new String[0]); 
         ^

Se posso aggiungere un cast di String[] verrà compilare ed eseguire perfettamente. Ma questo non è quello che mi aspetto quando ho guardato la firma del metodo toArray:

<T> T[] toArray(T[] a) 

Questo mi dice che non avrei dovuto lanciare. Cosa sta succedendo?

Edit:

Curiosamente, se cambio la dichiarazione l'elenco a:

List<?> l = Arrays.asList("a", "b", "c"); 

funziona anche. O List<Object>. Quindi non deve essere un List<String> come è stato suggerito. Sto iniziando a pensare che l'uso del tipo grezzo List cambi anche il modo in cui funzionano i metodi generici all'interno di quella classe.

Seconda modifica:

penso ho capito ora. Quello che Tom Hawtin ha scritto in un commento qui sotto sembra essere la migliore spiegazione. Se si utilizza un tipo generico nel modo raw, tutte le informazioni generiche da quell'istanza verranno cancellate dal compilatore.

risposta

29

Hai dimenticato di specificare il parametro tipo per la vostra lista:

List<String> l = Arrays.asList("a", "b", "c"); 

in questo caso è possibile scrivere sicurezza:

String[] a = l.toArray(new String[0]); 

senza alcun cast.

+1

Questo ha senso per me logicamente, ma non tecnicamente. Non mi sembra che il metodo toArray si preoccupi di ciò a cui E è vincolato (vale a dire, la classe di elemento dell'elenco). – waxwing

+1

la firma di toArray è "public T [] toArray (T [] a)", T è il tipo di componente della matrice passata in – dfa

+0

Inoltre non riesco a capirlo, peggio è che funziona anche utilizzando una lista (o Elenco ) per "l" –

1
List<String> l = Arrays.asList("a", "b", "c"); 

questo renderà compilazione, si sta utilizzando farmaci generici a dire "Questa è una lista di stringhe", così il metodo toArray sa quale tipo di array per tornare.

0

Questo perché l'elenco contiene oggetti, non stringhe. Se avessi dichiarato la tua lista come List<String>, il compilatore sarebbe felice.

3

o fare

List<?> l = Arrays.asList("a", "b", "c"); 

ancora strano

+0

+1 al contatore. Risolve il problema - ho notato la stessa stranezza. – waxwing

+1

peggiore: compila anche usando la lista ma dovrebbe bloccarsi in fase di runtime ...: - / –

0

List senza un tipo dichiarato stabilizzerà a "Elenco di oggetti", mentre List<?> significa "Elenco di sconosciuto".Nel mondo dei tipi generici è un dato di fatto che "Elenco di oggetti" è diverso da "Elenco di stringa" ma il compilatore non può dire lo stesso per "Elenco di sconosciuti". Se lo hai dichiarato come sconosciuto, allora, per quanto il compilatore può dire, va bene.

Il punto principale è dichiarare qualcosa come jolly? è diverso dal dichiararlo come Oggetto. Per saperne di più sui jolly here

Problemi correlati