23 votes

Bizarre génériques comportement de la Liste.toArray(T[])

Je suis tombé sur quelque chose de très basique, mais très déconcertant aujourd'hui. J'avais besoin de convertir une liste à un tableau. La liste contenue String des cas. Parfait exemple de l'utilisation de List.toArray(T[]), car je voulais un String[] de l'instance. Cela ne fonctionnerait pas, cependant, sans explicitement le casting du résultat d' String[].

Comme un 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. C'est presque une copie exacte de l'exemple dans la 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 d' String[] de compiler ET de l'exécuter parfaitement. Mais ce n'est pas ce que j'attends, quand j'ai vu la signature de la méthode toArray:

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

Cela me dit que je ne devrais pas avoir à jeter. Ce qui se passe?

Edit:

Curieusement, si je change la déclaration de la liste à:

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

il fonctionne également. Ou List<Object>. Donc il n'a pas à être un List<String> comme l'avait suggéré. Je commence à penser que l'utilisation du raw List type modifie la perception de méthodes génériques à l'intérieur que le travail en classe.

Deuxième édition:

Je crois que je comprends 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 dans le raw façon, tous les génériques de l'information à partir de cette instance seront effacées par le compilateur.

29voto

dfa Points 54490

vous avez oublié de spécifier le paramètre de type de 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 n'importe quelle distribution.

3voto

Carlos Heuberger Points 11804

ou ne

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

toujours étrange

1voto

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

cela permettra de compiler, vous êtes à l'aide de médicaments génériques à dire "ceci est une liste de Chaînes" de sorte que la méthode toArray sait de quel type de tableau à retourner.

0voto

JRL Points 36674

C'est parce que votre liste contient des objets, pas des chaînes de caractères. Aviez-vous déclaré votre liste List<String>, le compilateur pourrait être heureux.

0voto

henrik Points 410

List sans un type déclaré par défaut "Liste d'Objets" tout en List<?> signifie Liste des "inconnus". Dans le monde de types génériques, il est un fait que la "Liste d'Objets" est différent de "Liste de Chaîne", mais le compilateur ne peut pas dire la même chose pour la Liste des "inconnus". Si vous avez déclaré que l'inconnu puis, aussi loin que le compilateur ne peut pas savoir, c'est OK.

Le point principal est que déclarer que quelque chose comme le générique ? est différente de la déclarer comme Objet. Lire plus sur les jokers ici

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X