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.