Lidando com uma ArrayStoreException

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

lança

 java.lang.ArrayStoreException: java.lang.Integer 

enquanto

 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; 

não faz.

Existe alguma outra maneira de lidar com essa exceção sem criar um array temporário String[] ?

Em Java, uma matriz também é um object .

Você pode colocar um object de um subtipo em uma variável de um supertipo . Por exemplo, você pode colocar um object String em uma variável Object .

Infelizmente, a definição da matriz em Java está de alguma forma quebrada. String[] é considerado um subtipo de Object[] , mas isso está errado ! Para uma explicação mais detalhada, leia sobre “covariância e contravariância”, mas a essência é esta: Um tipo deve ser considerado um subtipo de outro tipo apenas se o subtipo preencher todas as obrigações do supertipo. Isso significa que, se você obtiver um object de subtipo em vez de um object de supertipo, não deverá esperar um comportamento contraditório ao contrato de supertipo.

O problema é que String[] suporta apenas uma parte do contrato Object[] . Por exemplo, você pode ler valores de Object[] de Object[] . E você também pode ler valores Object (que são objects String ) de String[] . Por enquanto, tudo bem. Problema é com a outra parte do contrato. Você pode colocar qualquer Object em Object[] . Mas você não pode colocar qualquer Object em String[] . Portanto, String[] não deve ser considerado um subtipo de Object[] , mas a especificação Java diz que é. E assim temos consequências assim.

(Note que uma situação semelhante apareceu novamente com as classs genéricas, mas desta vez foi resolvido corretamente . List não é um subtipo de List ; e se você quer ter um supertipo comum para estes, você precisa List , que é somente leitura. É assim que deve ser também com matrizes; mas não é. E devido à compatibilidade com versões anteriores, é tarde demais para alterá-lo.)

Em seu primeiro exemplo, a function String.split cria um object String[] . Você pode colocá-lo em uma variável Object[] , mas o object permanece String[] . É por isso que ele rejeita um valor Integer . Você precisa criar um novo array Objects[] e copiar os valores. Você pode usar a function System.arraycopy para copiar os dados, mas não pode evitar a criação da nova matriz.

Não, não há como evitar a cópia da matriz que split retornos.

O array que split retorna é na verdade um String[] , e Java permite que você atribua isso a uma variável do tipo Object[] . Ainda é realmente uma String[] no entanto, quando você tentar armazenar algo diferente de uma String , você receberá uma ArrayStoreException .

Para informações básicas, ver 4.10.3. Subtipagem entre os tipos de matriz na especificação da linguagem Java.

Existem outras opções, como a implementação do seu próprio método split, que retorna uma matriz de objects diretamente. Não tenho certeza do que realmente incomoda você com a matriz temporária de String?

BTW, você pode encurtar seu código com algumas linhas usando System.arrayCopy em vez de implementar seu próprio loop para copiar os elementos da matriz:

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