使用类型转换的 Java 数组初始化

2022-09-04 03:01: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"};

所以的运行时类型恰恰是哪些不能转换成.arr2Object[]String[]

但是这里的事情变得很奇怪,因为Java数组是协变的:是的子类,并且恰好是一个,从到以后的转换应该工作。String[]Object[]arr2String[]Object[]String[]arr2

对此的任何解释都值得高度赞赏。


答案 1

因为是一个,没有什么能阻止你写作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; 

编译器根据声明确定数组是希望数组是 a 还是 a。Object[]String[]


答案 2

arr2 正好是一个字符串[]

不,它不是 - 正如你所说,它是一个 - 你的行等同于: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());

推荐