Pregunta Tratar con una ArrayStoreException


Object[] o = "a;b;c".split(";");
o[0] = 42;

tiros

java.lang.ArrayStoreException: java.lang.Integer

mientras

String[] s = "a;b;c".split(";");
Object[] o = new Object[s.length];
for (int i = 0; i < s.length; i++) {
    o[i] = s[i];
}
o[0] = 42;

no.

¿Hay alguna otra forma de lidiar con esa excepción sin crear un temporal String[] ¿formación?


34
2017-09-11 12:40


origen


Respuestas:


En Java, una matriz también es objeto.

Puedes poner un objeto de subtipo en una variable de un supertipo. Por ejemplo, puedes poner un String objeto en un Object variable.

Desafortunadamente, la definición de matriz en Java se rompe de alguna manera. String[] se considera un subtipo de Object[], pero eso es incorrecto! Para una explicación más detallada, lea sobre "covarianza y contravarianza", pero la esencia es esta: un tipo debe considerarse un subtipo de otro tipo solo si el subtipo cumple todas las obligaciones del supertipo. Esto significa que si obtiene un objeto de subtipo en lugar de un objeto de supertipo, no debe esperar un comportamiento contradictorio con un contrato de supertipo.

El problema es que String[] solo admite una parte de Object[] contrato. Por ejemplo, puedes leer  Object valores de Object[]. Y también puedes leer  Object valores (que son String objetos) de String[]. Hasta aquí todo bien. El problema es con la otra parte del contrato. Puedes poner alguna  Object dentro Object[]. Pero no puedes poner alguna  Object dentro String[]. Por lo tanto, String[] no debe considerarse un subtipo de Object[], pero la especificación de Java dice que sí. Y así tenemos consecuencias como esta.

(Tenga en cuenta que una situación similar apareció de nuevo con las clases genéricas, pero esta vez se resolvió correctamente. List<String> es no un subtipo de List<Object>; y si quiere tener un supertipo común para estos, necesita List<?>, que es de solo lectura. Así es como debería ser también con matrices; pero no lo es. Y debido a la compatibilidad con versiones anteriores, es demasiado tarde para cambiarlo).

En tu primer ejemplo, String.split la función crea un String[] objeto. Puedes ponerlo en una Object[] variable, pero el objeto permanece String[]. Es por eso que rechaza un Integer valor. Tienes que crear un nuevo Objects[] array, y copia los valores. Podrías usar el System.arraycopy función para copiar los datos, pero no puede evitar la creación de la nueva matriz.


61
2017-09-11 12:56



No, no hay forma de evitar copiar la matriz split devoluciones.

La matriz que split vuelve es en realidad una String[]y Java te permite asignar eso a una variable de tipo Object[]. Todavía es realmente un String[] Sin embargo, cuando intenta almacenar algo más que un String en él, obtendrás un ArrayStoreException.

Para información de fondo ver 4.10.3. Subtipificación entre tipos de matriz en la Especificación del lenguaje Java.


6
2017-09-11 12:44



Por supuesto, existen otras opciones, como que implementa su propio método de división, que devuelve una matriz de objetos directamente. No estoy seguro de qué es lo que realmente te molesta con la matriz de cadenas temporal.

Por cierto, puede acortar su código con unas pocas líneas usando System.arrayCopy en lugar de implementar su propio bucle para copiar los elementos de la matriz:

System.arrayCopy(s, 0, o, 0, s.length);

0
2017-09-11 13:03



Si no es necesario usar una "división" ... Entonces puede evitar copiar ...


-1
2017-09-11 13:13