使用类型转换进行Java Array初始化

时间:2015-07-29 12:41:49

标签: java casting array-initialization

以下代码让我感到困惑:

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是协变的: String[]Object[]的子类,而arr2只是String[],从Object[]String[]转回arr2工作

对此的任何解释都表示高度赞赏。

4 个答案:

答案 0 :(得分:6)

因为arr2Object[],所以没有什么能阻止你写作

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; 

编译器根据您的声明确定您的阵列是Object[]还是String[]

答案 1 :(得分:5)

  

arr2正是一个String []

不,它不是 - 如你所说的那样Object[] - 你的行相当于:

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

发生<{1}} 发生以包含目前所有字符串引用的元素......但您也可以写:

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

答案 2 :(得分:3)

几乎正确。你的逻辑存在缺陷:

arr2 is exactly a String[]

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

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

太。

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

答案 3 :(得分: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"};