2009-07-02 4 views
23

Je suis tombé sur quelque chose de très basique mais extrêmement déconcertant aujourd'hui. J'avais besoin de convertir une liste en tableau. La liste contenait String instances. Exemple parfait d'utiliser List.toArray(T[]), puisque je voulais une instance String[]. Cela ne fonctionnerait pas, cependant, sans explicitement le résultat à String[].Comportement des génériques impairs de List.toArray (T [])

En tant que scénario de test, j'ai utilisé le code suivant:

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)); 
    } 
} 

qui ne compile pas. Il est presque une copie exacte de l'exemple dans le javadoc, mais le compilateur dit ce qui suit:

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

Si j'ajoute un casting à String[] il compiler et exécuter parfaitement. Mais ce n'est pas ce que je pense quand je regardais la signature du toArray:

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

Cela me dit que je ne devrais pas avoir à lancer. Que se passe-t-il?

Edit:

Chose curieuse, si je change la déclaration de liste:

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

cela fonctionne aussi. Ou List<Object>. Donc, il ne doit pas être un List<String> comme cela a été suggéré. Je commence à penser que l'utilisation du type brut List modifie également le fonctionnement des méthodes génériques à l'intérieur de cette classe.

Deuxième édition:

Je pense que je reçois maintenant. Ce que Tom Hawtin a écrit dans un commentaire ci-dessous semble être la meilleure explication. Si vous utilisez un type générique de manière brute, toutes les informations génériques de cette instance seront effacées par le compilateur.

Répondre

29

vous avez oublié de spécifier le paramètre de type pour votre liste:

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

dans ce cas, vous pouvez écrire la sécurité:

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

sans aucun casting.

+1

Cela me semble logique, mais pas techniquement. Il ne me semble pas que la méthode toArray se soucie de ce qui est lié à E (c'est-à-dire la classe d'éléments de la liste). – waxwing

+1

la signature de toArray est "public T [] toArray (T [] a)", T est le type de composant du tableau passé en – dfa

+0

Je ne peux pas non plus le comprendre, pire est qu'il fonctionne également en utilisant une liste (ou la liste ) pour "l" –

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

cela rendra la compilation, vous utilisez des médicaments génériques à dire « ceci est une liste de chaînes » de sorte que le toArray sait quel type de tableau pour revenir.

0

C'est parce que votre liste contient des objets, pas des chaînes. Si vous aviez déclaré votre liste comme List<String>, le compilateur serait heureux.

3

ou faire

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

encore étrange

+0

+1 pour contrer. Cela résout le problème - j'ai moi-même remarqué la même bizarrerie. – waxwing

+1

pire: il compile également en utilisant la liste , mais devrait tomber en panne à l'exécution ...: - / –

0

List sans type déclaré par défaut à "Liste des objets", tandis que List<?> signifie "Liste des inconnus".Dans le monde des types génériques, il est un fait que "List of Object" est différent de "List of String" mais le compilateur ne peut pas dire la même chose pour "List of unknown". Si vous l'avez déclaré comme inconnu alors, autant que le compilateur peut le dire, c'est OK.

Le point principal est que déclarer quelque chose comme le caractère générique? est différent de le déclarer comme objet. En savoir plus sur les caractères génériques here

Questions connexes