14

以下代码让我感到困惑:

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;

我试图理解为什么这两个初始化彼此不同。第一个是发布声明,而第二个是快捷方式。两者都被声明为Object[]

我的幼稚理解是:

Object[] arr2 = {"a", "b", "c"}; // is a syntax sugar of
Object[] arr2 = new Object[] {"a", "b", "c"};

所以运行时类型arr2正是Object[]不能转换成String[].

但是这里的事情变得很奇怪,因为 Java Array 是 covariant: String[]的子类,Object[]并且arr2正是 a的子类,从toString[]转换回on应该可以工作。Object[]String[]arr2

对此的任何解释都非常感谢。

4

4 回答 4

6

因为arr2是一个Object[],所以没有什么能阻止你写作

arr2[0] = new Object();

就在你的演员之前,演员无论如何都不再有意义的情况。

由于初始化程序语法的工作方式,还请注意以下几点:

Object x = {"a", "b"}; // error: illegal initializer for Object
Object[] a = {"a", "b"}; //a has class [Ljava.lang.Object; 
String[] b = {"a", "b"};  //b has class [Ljava.lang.String; 

编译器根据您的声明确定您是否希望您的数组为 anObject[]或 a String[]

于 2015-07-29T12:46:10.190 回答
5

arr2 正是一个 String[]

不,它不是 - 它是一个Object[],正如你所说 - 你的行相当于:

Object[] arr2 = new Object[] {"a", "b", "c"};

Object[]碰巧有目前所有字符串引用的元素......但你也可以写

arr2[0] = new Object(); // Fine, because arr2 is an Object[]

如果你对 做同样的事情arr1,你会得到一个例外:

arr1[0] = new Object(); // Fine at compile time, will throw an exception

您当然可以使用以下方法检查对象的实际执行时间类型getClass

System.out.println(arr2.getClass());
于 2015-07-29T12:46:26.070 回答
3

几乎正确。你的逻辑在这里有缺陷:

arr2 is exactly a String[]

不它不是。它是一个对象数组。您刚刚将字符串添加到此数组中的事实毫无意义。你可以写

arr2 = {"a", new Integer(5) };

也。

可能这更清楚了,为什么不允许将这样的数组转换为 String[]。

于 2015-07-29T12:47:10.457 回答
1
Object[] arr2 = {"a", "b", "c"};

在这种情况下,您声明的数组等于

Object[] arr2 = new Object[] {"a", "b", "c"};

因此,arr2 中的元素可以是任何类型的Object. 并且在线

String[] b = (String[]) arr2; // ClassCastException

因为您正在尝试将整体Object[]转换为String[].

与第一个一样,您明确告诉所有对象都是字符串

Object[] arr1 = new String[]{"a", "b", "c"};
于 2015-07-29T12:48:53.553 回答