Skip to content
Advertisement

Dealing with an ArrayStoreException

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

throws

java.lang.ArrayStoreException: java.lang.Integer

while

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;

doesn’t.

Is there any other way to deal with that exception without creating a temporary String[] array?

Advertisement

Answer

In Java an array is also an object.

You can put an object of a subtype into a variable of a supertype. For example you can put a String object into an Object variable.

Unfortunately, the array definition in Java is somehow broken. String[] is considered a subtype of Object[], but that is wrong! For a more detailed explanation read about “covariance and contravariance”, but the essence it this: A type should be considered a subtype of another type only if the subtype fulfills all obligations of the supertype. That means, that if you get a subtype object instead of a supertype object, you should not expect behavior contradictory to supertype contract.

Problem is that String[] only supports a part of Object[] contract. For example you can read Object values from Object[]. And you can also read Object values (which happen to be String objects) from String[]. So far so good. Problem is with the other part of contract. You can put any Object into Object[]. But you cannot put any Object into String[]. Therefore, String[] should not be considered a subtype of Object[], but Java specification says it is. And thus we have consequences like this.

(Note that a similar situation appeared again with the generic classes, but this time it was solved correctly. List<String> is not a subtype of List<Object>; and if you want to have a common supertype for these, you need List<?>, which is read-only. This is how it should be also with arrays; but it’s not. And because of the backwards compatibility, it is too late to change it.)

In your first example the String.split function creates a String[] object. You can put it into a Object[] variable, but the object remains String[]. This is why it rejects an Integer value. You have to create a new Objects[] array, and copy the values. You could use the System.arraycopy function to copy the data, but you cannot avoid creating the new array.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement