Can someone explain me how arrays really work in Java.
I was surprised by the following code:
Object test = new Object[2][2];
Object test2 = new Object[] {
new Object[2],new Object[2]
};
Object test3 = new Object[2][];
((Object[])test3)[0] = new Object[2];
((Object[])test3)[1] = new Object[2];
System.out.println(test instanceof Object[]);
System.out.println(test instanceof Object[][]);
System.out.println(test2 instanceof Object[]);
System.out.println(test2 instanceof Object[][]);
System.out.println(test3 instanceof Object[]);
System.out.println(test3 instanceof Object[][]);
only test2 is not an instance of Object[][]
What is the distinction at runtime?
Edit: i see some answers. Jon Skeet, please notice that i can do:
Object[] test4 = (Object [])test;
test4[0] = "blaaa";
test4[1] = "toto";
System.out.println(test4);
test instanceof Object[] returns true, and no exception is raised at runtime on the cast. According to the SCJP book of Sierra & Bates, test IS-A Object[][] but also a Object[]
But when trying to reassigning a new value with "test4[0] = "blaaa";", i get an exception: Exception in thread "main" java.lang.ArrayStoreException: java.lang.String at Main.main(Main.java:24)
So it seems at runtime, both test and test2 IS-A Object[], and both contains object arrays, but only one of them IS-A Object[][]
test2
refers to an array of two elements. Its type is just Object[]
- so those elements can refer to any objects. In particular, you could write:
// Valid
Object[] foo = (Object[]) test2;
foo[0] = "hello";
whereas that wouldn't work for test
:
// Invalid - test isn't just an Object[], it's an Object[][]
Object[] foo = (Object[]) test;
test[0] = "hello";
because the element type of the array that test
refers to is Object[]
rather than Object
. The array "knows" that each element should be null or a reference to an Object[]
, so the VM will prevent it from storing a string.
You can convert test
to an Object[]
in the same way that you can convert a String[]
to an Object[]
- that's called array covariance, and it was a mistake to allow it in my opinion. The VM has to check stores at execution time, as we've seen.