处理ArrayStoreException

Object[] o = "a;b;c".split(";"); o[0] = 42; 

 java.lang.ArrayStoreException: java.lang.Integer 

 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; 

没有。

有没有其他的方式来处理这个exception,而不创build一个临时的String[]数组?

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

你可以把一个子types的对象放入一个超types的variables中。 例如,你可以把一个String对象放入一个Objectvariables中。

不幸的是,Java中的数组定义被打破了。 String[]被认为是Object[]一个子types,但这是错误的 ! 关于“协方差和相反性”的更详细的解释,其实质是:只有当子types满足超types的所有义务时 ,types才应被视为另一types的子types。 这意味着,如果你得到一个子types对象而不是一个超types对象,你不应该期望行为与超types合约矛盾。

问题是String[]只支持Object[]契约的一部分 。 例如,您可以从Object[] 读取 Object值。 你也可以从String[] 读取 Object值(恰好是String对象)。 到现在为止还挺好。 问题在于合同的其他部分。 你可以把任何 Object放入Object[] 。 但是你不能把任何 Object放到String[] 。 因此, String[]不应该被认为是Object[]一个子types,但Java规范说这是。 因此,我们有这样的后果。

(请注意类似的情况再次出现在generics类中,但是这一次正确解决了 List<String> 不是 List<Object>的子types,如果你想拥有一个公共的超types,你需要List<?> ,它是只读的,这与数组是一样的,但是它不是,而且由于向后兼容性,改变它为时已晚。

在你的第一个例子中, String.split函数创build一个String[]对象。 你可以把它放到一个Object[]variables中,但是这个对象仍然是String[] 。 这就是拒绝Integer值的原因。 你必须创build一个新的Objects[]数组,并复制这些值。 您可以使用System.arraycopy函数来复制数据,但不能避免创build新的数组。

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

split返回的数组实际上是一个String[] ,Java允许您将其分配给Object[]types的variables。 但是,它仍然是一个String[] ,所以当你试图存储除String之外的其他东西时,你将得到一个ArrayStoreException

有关背景信息,请参阅4.10.3。 Java语言规范中的数组types之间的子types 。

当然还有其他的select,比如你实现你自己的split方法,直接返回一个Object数组。 我不确定究竟是什么让你感到困扰与临时的string数组?

顺便说一句,你可以使用System.arrayCopy几行缩短你的代码,而不是实现你自己的循环来复制数组元素:

 System.arrayCopy(s, 0, o, 0, s.length); 

如果没有必要使用“分割”…那么你可以避免复制…