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