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[][]
test2refers to an array of two elements. Its type is justObject[]– so those elements can refer to any objects. In particular, you could write:whereas that wouldn’t work for
test:because the element type of the array that
testrefers to isObject[]rather thanObject. The array “knows” that each element should be null or a reference to anObject[], so the VM will prevent it from storing a string.You can convert
testto anObject[]in the same way that you can convert aString[]to anObject[]– 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.