The following code makes me confused:
Object[] arr1 = new String[]{"a", "b", "c"};
Object[] arr2 = {"a", "b", "c"};
String[] a = (String[]) arr1; // ok
String[] b = (String[]) arr2; // ClassCastException
System.out.println(arr1.getClass().getName()); // [Ljava.lang.String;
System.out.println(arr2.getClass().getName()); // [Ljava.lang.Object;
I am trying to understand why the two initialization are different from each other. The first one is a post declaration, while the second one is a shortcut. The two are both declared as Object[]
My naive understanding is that:
Object[] arr2 = {"a", "b", "c"}; // is a syntax sugar of
Object[] arr2 = new Object[] {"a", "b", "c"};
So the runtime type of arr2
is exactly Object[]
which can not be converted into String[]
.
But the things get strange here, because Java Array is covariant:
String[]
is a subclass of Object[]
and arr2
is exactly a String[]
, casting back from Object[]
to String[]
on arr2
should work.
Any explanation on this is high appreciated.
arr2 is exactly a String[]
No, it isn't - it's an Object[]
, as you said - your line is equivalent to:
Object[] arr2 = new Object[] {"a", "b", "c"};
It's an Object[]
which happens to have elements which are all string references at the moment... but you could also write:
arr2[0] = new Object(); // Fine, because arr2 is an Object[]
If you did the same thing with arr1
, you'd get an exception:
arr1[0] = new Object(); // Fine at compile time, will throw an exception
You can check the actual execution-time type of an object using getClass
of course:
System.out.println(arr2.getClass());
See more on this question at Stackoverflow