1183 votes

Convertir ArrayList<String> String []

Je travaille dans l'android de l'environnement et ont essayé le code suivant, mais il ne semble pas fonctionner.

String [] stockArr = (String[]) stock_list.toArray();

Si je définis comme suit:

String [] stockArr = {"hello", "world"};

elle fonctionne. Il y a une chose que je suis absent?

1806voto

Prince John Wesley Points 22418

L'utilisation de ce genre.

ArrayList<String> stockList = new ArrayList<String>();
stockList.add("stock1");
stockList.add("stock2");
String[] stockArr = new String[stockList.size()];
stockArr = stockList.toArray(stockArr);
for(String s : stockArr)
    System.out.println(s);

961voto

st0le Points 15318

Essayez ceci

String[] arr = list.toArray(new String[list.size()]);

315voto

Stephen C Points 255558

Ce qui se passe est que l' stock_list.toArray() est la création d'un Object[] plutôt qu'un String[] , et donc le transtypage est un échec.

Le bon code serait:

  String [] stockArr = stockList.toArray(new String[stockList.size()]);

ou même

  String [] stockArr = stockList.toArray(new String[0]);

Pour plus de détails, reportez-vous à la documentation javadoc pour les deux surcharges de la List.toArray.

(À partir d'un point de vue technique, la raison de cette API de comportement / de conception est qu'une mise en œuvre de l' List<T>.toArray() méthode n'a pas d'informations de ce que l' <T> est au moment de l'exécution. Tous il sait que le raw type d'élément est - Object. Par contre, dans les autres cas, le tableau de paramètre donne le type de base de la matrice. (Si le tableau fourni est assez grand, il est utilisé. Sinon, un nouveau tableau de même type et de même une plus grande taille sera alloué et retourné comme résultat.)

160voto

Vitalii Fedorenko Points 17469

Une alternative à Java 8:

String[] strings = list.stream().toArray(String[]::new);

88voto

Pshemo Points 34648

Je peux voir beaucoup de réponses qui montrent comment résoudre le problème, mais seulement Etienne la réponse est d'essayer de le point pourquoi le problème se produit donc vais essayer de dire quelque chose de plus sur ce sujet

Pourquoi String[] stockArr = (String[]) stock_list.toArray(); ne fonctionnent pas?

En Java, les génériques de travail au moment de la compilation. Lors de l'exécution d'infos sur le type générique (comme dans votre cas <String>) sont supprimés et remplacés par Object type (regardez le type d'effacement). C'est pourquoi, toArray() n'ont aucune idée sur ce que précise le type à utiliser pour créer un nouveau tableau et utilise Object comme la plus sûre de type (chaque classe s'étend de l'Objet de sorte qu'il peut être utilisé pour stocker n'importe quel type d'instances).

Maintenant, le problème, c'est que vous ne pouvez pas jeter instance de Object[] de String[].

Pourquoi? Jetez un oeil à cet exemple: (permet de supposer que class B extends A)

A a = new A();
B b = (B)a;

Bien que de compiler, à l'exécution, il va jeter ClassCastException car instance de la classe A ne peut pas être jeté à la classe B. Pourquoi est-ce pas? Une des raisons est que B ne peut y avoir de nouvelles méthodes/champs que l'Un ne fonctionne pas, quelqu'un pourrait essayer de l'utiliser par l'intermédiaire b de référence. Serait-ce sans danger? Pas de. Cela risque de rendre le plantage de l'application.

Seule façon d'être en mesure de convertir l'objet de référence A a de le stocker dans de référence B b , c'est quand, en vertu a est en fait instance d' B classe (ou de la même classe qui s'étend B) comme dans cet exemple:

A a = new B(); // Here reference "a" holds object of type B
B b = (B)a;    // so now casting is safe (at runtime JVM is sure that `b` reference
               // can safely access all its methods from `B` class which `A` could not have

En bref, b savent que l'objet est en fait instance d' B classe de façon à ce casting est sûr.


Mais revenons à vos tableaux exemple. Comme vous le voyez en question, nous ne pouvez pas jeter instance de Object[] tableau plus précis de type String[] comme

Object[] arr = new Object[] { "ab", "cd" };
String[] arr2 = (String[]) arr;

Ici, le problème est un peu différent. Maintenant on est sûr qu' String[] tableau n'aura pas d'autres champs ou méthodes, car chaque tableau en charge uniquement:

  • [] de l'opérateur,
  • length déposée,
  • les méthodes héritées de l'Objet supertype),

Le problème est qu' Object[] tableau permet de stocker des objets à côté d' Strings (par exemple, Integers), il est donc hautement probable que certains beau jour on finira par l'invocation de la méthode comme strArray[i].substring(1,3) sur instance de la classe qui n'ont pas cette méthode.

Alors pour s' assurer que cette situation ne jamais arriver en Java références de tableau ne peut contenir qu'

  • les instances de tableau de même type comme référence (String[] peut contenir String[])
  • les instances de tableau de sous-type (Object[] peut contenir String[] car String est sous-type de l' Object),

mais ne peut pas tenir

  • tableau de supertype de type de tableau de référence (String[] ne peuvent pas contenir d' Object[])
  • tableau de type qui n'est pas lié au type de référence (Integer[] ne peuvent pas contenir d' String[])

En d'autres termes, quelque chose comme cela, c'est OK

Object[] arr = new String[] { "ab", "cd" }; //OK - arr holds array of subtype of Object (String)
String[] arr2 = (String[]) arr; //OK - arr2 will hold same type as reference

On pourrait dire qu'une façon de résoudre ce problème est de vérifier le type le plus fréquent de tous les éléments de liste et créer une matrice de ce type, mais cela ne marchera pas dans les situations où tous les éléments de la liste seront dérivés de type générique. Prendre un coup d'oeil

//B extends A
List<A> elements = new ArrayList<A>();
elements.add(new B());
elements.add(new B());

maintenant, le type le plus fréquent est B, pas A donc toArray() serait de retour tableau d' B classe new B[] et un tel tableau ne peut pas être jeté à l' A[] car elle pourrait conduire à essayer d'ajouter des éléments qui s'étendent A mais pas B de ce tableau.


Donc, seule solution à ce problème est d'indiquer explicitement ce type de tableau toArray() doit être retourné par le passage de ce type, comme un argument de méthode comme

String[] arr = list.toArray(new String[list.size()]);

ou

String[] arr = list.toArray(new String[0]); //if size of array is smaller then list it will be automatically adjusted.

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