java - for - ¿Por qué Arrays.asList(…).toArray(). GetClass() da resultados diferentes en JDK 8 y 9?
java for developers (2)
Esta pregunta ya tiene una respuesta aquí:
- array cast Java 8 vs Java 9 2 respuestas
¿Por qué la siguiente condición devuelve true
con JDK 8, mientras que devuelve false
con JDK 9?
String[].class == Arrays.asList("a", "b").toArray().getClass()
El tipo de List
devuelto por asList
es Arrays$ArrayList
. El método toArray
en JDK 8 en esa clase es:
@Override
public Object[] toArray() {
return a.clone();
}
Pero en JDK 9+ es:
@Override
public Object[] toArray() {
return Arrays.copyOf(a, a.length, Object[].class);
}
En ambos casos String[]
se pasa una String[]
a asList
, pero en el caso de JDK 8 se clona, lo que conserva su tipo de matriz ( String[]
), y en JDK 9+ se copia utilizando Arrays.copyOf
con la nueva matriz explícita tipo de Object[]
.
Esta diferencia significa que en JDK 8 Arrays.asList("a", "b").toArray().getClass()
devuelve String[]
y en JDK 9+ devuelve Object[]
, por lo que en JDK 9+ su expresión evaluar a false
.
La razón de este cambio proviene de JDK-6260652 con la motivación:
La documentación de la colección afirma que
collection.toArray()
es "idéntico en función" a
collection.toArray(new Object[0]);
Sin embargo, la implementación de
Arrays.asList
no sigue esto: si se crea con una matriz de un subtipo (por ejemplo,String[]
), sutoArray()
devolverá una matriz del mismo tipo (porque usaclone()
) en lugar de unObject[]
.Si uno trata más tarde de almacenar no cadenas (o lo que sea) en esa matriz, se lanza una
ArrayStoreException
.
Así que este cambio se hizo para arreglar el comportamiento anterior.
Si este es un problema para usted, la nota de lanzamiento relacionada ofrece esto como una solución alternativa:
Si se produce este problema,
toArray(T[])
escribir el código para usar el formulario one-argtoArray(T[])
y proporcione una instancia del tipo de matriz deseado. Esto también eliminará la necesidad de un yeso.
String[] array = list.toArray(new String[0]);
Yo diría que esto fue un error en JDK 8 y antes de que se haya solucionado.
List<T>.toArray()
siempre se declaró como Object[]
devuelto Object[]
(ver JavaDoc ) - que en efecto devolvió la String[]
en un caso especial fue un error.