Java 为什么可以';t将对象[]强制转换为字符串[]

Java 为什么可以';t将对象[]强制转换为字符串[],java,arrays,casting,Java,Arrays,Casting,无误 Object[] a = new String[]{"12","34","56"}; String[] b = (String[]) a; Object a = new String[]{"12","34","56"}; String[] b = (String[]) a; 无误 Object[] a = new String[]{"12","34","56"}; String[] b = (String[]) a; Object a = new String[]{"12"

无误

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

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

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

    Object[] a = new Object[3];
    a[0] = "12";
    a[1] = "34";
    a[2] = "56";
    String[] b = (String[]) a;
    
    Object[] a = {"12","34","56"};    
    String[] b = (String[]) a;
    
  • 当然,如果将
    对象[]
    变量创建为
    字符串[]
    ,我们可以将其向下转换回
    字符串[]

    Object[] a = new String[]{"12","34","56"};
    
    arrayOfUrls = imageUrls.toArray(new String[imageUrls.size()]);
    

    我的问题是,当它被创建为
    Object[]
    时,为什么我们不能将
    Object[]
    强制转换为
    String[]
    ,但它的所有成员都是String?是出于安全原因还是实现此功能没有那么有用?

    因为您不是在强制转换数组的单个成员,而是在强制转换整个数组实例,该实例的类型为
    对象[]
    ,而不是
    字符串[]

    Object[] a = new String[]{"12","34","56"};
    
    arrayOfUrls = imageUrls.toArray(new String[imageUrls.size()]);
    
    这里的实例类型为
    String[]
    ,编译时类型为
    Object[]

    Object[] a = new String[]{"12","34","56"};
    
    arrayOfUrls = imageUrls.toArray(new String[imageUrls.size()]);
    
    在下一行中,您将把它转换回
    String[]
    ,这是允许的,因为实际类型或运行时类型是
    String[]

    Object[] a = new String[]{"12","34","56"};
    
    arrayOfUrls = imageUrls.toArray(new String[imageUrls.size()]);
    
    但是
    Object[]a=新对象[3]
    这里的实际类型和编译时类型是
    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;
    
    它在中定义。实质上,演员阵容:

     r = new RC[]; TC[] t = (TC[]) r;
    
    运行时“工作”iif RC是TC(或TC本身)的一个子类型。RC实际上是否只包含TCs是不相关的,并且也不使用r的编译时类型(重要的是运行时类型):

    • 您可以编写:
      r=newstring[];对象[]t=(对象[])r,但是
    • 不能写入
      r=新对象[];字符串[]t=(字符串[])r
    JLS摘录:

    如果T是数组类型TC[],即TC类型的组件数组,则会引发运行时异常,除非以下情况之一为真:

    • TC和RC是相同的基元类型
    • TC和RC是引用类型,可以通过递归应用这些用于转换的运行时规则将类型RC转换为TC
    在示例3和4中,RC=Object和TC=String,Object不是String的子类型。 在示例1和2中,RC=String和TC=String使其工作


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

    如果在强制转换时对象数组的所有成员都是字符串,则以后仍可以将非字符串的对象分配给此数组的元素。因此,您可以使用非字符串元素的字符串数组。

    以下是我可以想到的两个原因

    首先,如果更改原始数组,则强制转换的数组可能会变得无效。e、 g

     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[] 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.
    
    这提供了一种从
    对象[]
    快速创建
    字符串[]
    的方法

    Object[] a = new String[]{"12","34","56"};
    
    arrayOfUrls = imageUrls.toArray(new String[imageUrls.size()]);
    

    当然,假设
    imageUrls
    不是
    null

    这很有趣。您能告诉我类数组的名称和字符串[]的类名是什么吗?@DonLi:它们没有友好的名称(除了
    对象[]
    字符串[]
    )。内部名称类似于
    [Ljava.lang.Object;
    [Ljava.lang.String;
    。字符串数组的类名是
    [Ljava.lang.String;
    。由于它不是有效的标识符,因此不能在程序中直接使用它,但可以将其与反射API一起使用。您可以定义数组并执行
    getClass()
    在该数组实例上打印,您将得到该表示形式。更简单的是:类对象文本
    字符串[]。类在JLS中,它是TC[]=(TC[])RC[]。所以RC是Object,TC是Sting。如果Object是Sting,则可以将其转换为String。所以我仍然不明白。JLS没有解释为什么允许使用案例1和案例2,这两种情况将Object[]转换为String[],我已经详细阐述了一点。在第一个示例中,您没有将
    Object[]
    转换为
    String[]
    ,您正在将
    字符串[]
    (运行时类型)强制转换为
    字符串[]
    ,这是允许的。从JLS的角度来看,Assylias提供了一个很好的答案。Alex解释了为什么JLS不允许这样做。所以Alex的答案就是我想要的。谢谢大家,伙计们。