处理ArrayStoreException

sp0*_*00m 42 java arrays casting type-conversion

Object[] o = "a;b;c".split(";");
o[0] = 42;
Run Code Online (Sandbox Code Playgroud)

java.lang.ArrayStoreException: java.lang.Integer
Run Code Online (Sandbox Code Playgroud)

String[] s = "a;b;c".split(";");
Object[] o = new Object[s.length];
for (int i = 0; i < s.length; i++) {
    o[i] = s[i];
}
o[0] = 42;
Run Code Online (Sandbox Code Playgroud)

没有.

有没有其他方法来处理该异常而不创建临时String[]数组?

Vil*_*Búr 75

在Java中,数组也是一个对象.

您可以将子类型的对象放入超类型的变量中.例如,您可以将String对象放入Object变量中.

不幸的是,Java中的数组定义在某种程度上被打破了.String[]被认为是子类型Object[],但那是错误的!有关"协方差和逆变"的更详细解释,但其实质是:只有当子类型履行超类型的所有义务时,才应将类型视为另一种类型的子类型.这意味着,如果你得到一个子类型对象而不是一个超类型对象,你不应该期望与超类型契约相矛盾的行为.

问题是,String[]只支持部分Object[]合同.例如,您可以从中读取 ObjectObject[].您还可以从中读取 Object值(恰好是String对象)String[].到现在为止还挺好.问题在于合同的其他部分.你可以把任何东西 Object放进去Object[].但你不能把任何东西 Object放进去String[].因此,String[]不应该被视为子类型Object[],但Java规范说它是.因此我们有这样的后果.

(请注意,类似的情况,以与一般类又出现了,不过这次是解决正确,List<String>不是一个亚型List<Object>;如果你想拥有这些共同的超类型,你需要List<?>,它是只读的这是.它应该如何与数组;但它不是.并且由于向后兼容性,它改变它为时已晚.)

在第一个示例中,该String.split函数创建了一个String[]对象.您可以将其放入Object[]变量中,但对象仍然存在String[].这就是拒绝Integer价值的原因.您必须创建一个新Objects[]数组,然后复制这些值.您可以使用该System.arraycopy函数复制数据,但无法避免创建新数组.

  • http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ102 (2认同)

Jes*_*per 9

不,没有办法避免复制split返回的数组.

split返回的数组实际上是a String[],Java允许您将其分配给类型的变量Object[].它仍然是真的String[],所以当你试图存储其他东西而不是其中String的东西时,你会得到一个ArrayStoreException.

有关背景信息,请参见4.10.3.Java语言规范中的数组类型之间的子类型.