处理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
对象放入一个Object
variables中。
不幸的是,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);
如果没有必要使用“分割”…那么你可以避免复制…