web-dev-qa-db-fra.com

Pourquoi Arrays.asList (...). ToArray (). GetClass () donne-t-il des résultats différents dans JDK 8 et 9?

Pourquoi la condition suivante retourne true avec JDK 8, alors qu'elle retourne false avec JDK 9?

String[].class == Arrays.asList("a", "b").toArray().getClass()
44
Felix

Le type List renvoyé par asList est Arrays$ArrayList . La méthode toArray dans JDK 8 sur cette classe est:

@Override
public Object[] toArray() {
    return a.clone();
}

Mais dans JDK 9+ c'est:

@Override
public Object[] toArray() {
    return Arrays.copyOf(a, a.length, Object[].class);
}

Dans les deux cas, un String[] Est passé à asList, mais dans le cas JDK 8, il est cloné, qui conserve son type de tableau (String[]), Et dans JDK 9+ il est copié à l'aide de Arrays.copyOf avec le nouveau type de tableau explicite de Object[].

Cette différence signifie que dans JDK 8 Arrays.asList("a", "b").toArray().getClass() renvoie String[] Et dans JDK 9+ il retourne Object[], Donc dans JDK 9+ votre expression sera évaluée à false.

La raison de ce changement vient de JDK-6260652 avec la motivation:

La documentation de la Collection affirme que

collection.toArray()

est "identique en fonction" à

collection.toArray(new Object[0]);

Cependant, l'implémentation de Arrays.asList Ne suit pas ceci: s'il est créé avec un tableau d'un sous-type (par exemple String[]), Sa toArray() renverra un tableau du même type (car il utilise clone()) au lieu d'un Object[].

Si l'on essaie plus tard de stocker des non-chaînes (ou autre) dans ce tableau, un ArrayStoreException est jeté.

Cette modification a donc été apportée pour corriger le comportement précédent.


Si c'est un problème pour vous, le release note associé propose ceci comme solution de contournement:

Si ce problème se produit, réécrivez le code pour utiliser le formulaire à un argument toArray(T[]) et fournissez une instance du type de tableau souhaité. Cela éliminera également le besoin d'un casting.

String[] array = list.toArray(new String[0]);
51
Jorn Vernee

Je dirais que c'était un bug dans JDK 8 et avant cela a été corrigé.

List<T>.toArray() a toujours été déclaré comme retournant Object[] (voir JavaDoc ) - qu'il a effectivement renvoyé String[] dans un cas particulier était une erreur.

12
Thomas Kläger