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.