为什么不能将Object 转换为String

  1. 没错

    Object[] a = new String[]{"12","34","56"}; String[] b = (String[]) a; 
  2. 没错

     Object a = new String[]{"12","34","56"}; String[] b = (String[]) a; 
  3. 运行时错误:ClassCastException

     Object[] a = new Object[3]; a[0] = "12"; a[1] = "34"; a[2] = "56"; String[] b = (String[]) a; 
  4. 运行时错误:ClassCastException

     Object[] a = {"12","34","56"}; String[] b = (String[]) a; 

当然,如果将Object[]变量创建为String[] ,我们可以将其转换回String[]

我的问题是为什么我们不能将Object[]String[]当它被创建为Object[]但它的所有成员都是String? 是因为安全原因还是没有用来实现这个?

这是我能想到的两个原因。

首先,如果更改原始数组,则铸造数组可能无效。 例如

  Object[] a = {"12","34","56"}; String[] b = (String[]) a; // pretend this is legal. a and b now point to the same array a[0] = new Object(); // clearly ok String x = b[0]; // No longer a string! Bad things will happen! 

其次,您选择的示例非常简单,但是如果您有一个非常大的Object[]数组并且编译器不清楚它是什么填充它,那么它无法validation数组的每个元素是否满足转换。

 Object[] a = new Object[10000]; // lots of weird and whacky code to fill the array with strings String[] b= (String[]) a; // valid or no? The best-defined answer is to say no. 

它在JLS#5.5.3中定义。 实质上,演员:

  r = new RC[]; TC[] t = (TC[]) r; 

在运行时“工作”iif RC是TC(或TC本身)的子类型。 RC是否实际上只包含TC是无关紧要的,r的编译时类型也没有使用(重要的是运行时类型):

  • 你可以写: r = new String[]; Object[] t = (Object[]) r; r = new String[]; Object[] t = (Object[]) r; 但是
  • 你不能写r = new Object[]; String[] t = (String[]) r; r = new Object[]; String[] t = (String[]) r;

JLS提取物:

如果T是数组类型TC [],即TC类型的组件数组,则抛出运行时exception,除非满足下列条件之一:

  • TC和RC是相同的原始类型。
  • TC和RC是引用类型,通过递归应用这些运行时规则进行转换,可以将类型RC转换为TC。

在示例3和4中,RC = Object和TC = String,Object不是String的子类型。 在您的示例1和2中,RC = String和TC = String,因此它可以工作。

注意:此上下文中的类型是运行时类型。

因为您没有构建数组的单个成员 ,所以您要转换整个数组实例 ,该实例的类型为Object[]而不是String[]

 Object[] a = new String[]{"12","34","56"}; 

这里的实例是String[]类型,编译时类型是Object[]

在下一行中,您将其转换回String[] ,允许将其作为实际类型或运行时类型为String[]

但是Object[] a = new Object[3]; 这里的实际类型和编译时间类型是Object[] ,它不是String[] 。 所以Object[]不能是String[]

 Object[] a = new Object[1]; a[0] = "a"; //Actual type String 

所以你可以这样做:

 String aStr = (String)a[0]; 

数组对象不仅仅是它们元素的集合,它们就像其他对象一样有类。 字符串数组的类是对象数组的子类。 这就是为什么你的1或2没有错误,但最后两个相当于

 Object o = new Object(); String s = (String) o; 

如果所有成员Object数组在转换时都是字符串,那么您仍然可以在以后将不是字符串的对象分配给此数组的元素。 所以你会得到String数组,其元素不是字符串。

这篇文章提供了一种从Object[]快速创建String[] Object[]

 arrayOfUrls = imageUrls.toArray(new String[imageUrls.size()]); 

当然假设imageUrls不为null