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;
没有。
有没有其他方法可以在不创建临时 String[]
数组的情况下处理该异常?
原文由 sp00m 发布,翻译遵循 CC BY-SA 4.0 许可协议
在 Java 中,数组也是一个 _对象_。
您可以将 子类型 的对象放入 超类型 的变量中。例如,您可以将
String
对象放入Object
变量中。不幸的是,Java 中的数组定义不知何故被破坏了。
String[]
被认为是Object[]
的子类型,但这是 错误 的!有关更详细的解释,请阅读“协变和逆变”,但其本质是:只有当子类型满足超类型的 所有义务 时,类型才应被视为另一种类型的子类型。这意味着,如果你得到一个子类型对象而不是超类型对象,你不应该期望行为与超类型契约相矛盾。问题是
String[]
只支持 一部分Object[]
合同。例如,您可以从Object[]
读取Object
值。您还可以从 — 读取Object
值(恰好是String
String[]
)。到目前为止,一切都很好。问题出在合同的另一部分。您可以将 任何Object
放入Object[]
。但是您不能将 任何Object
放入String[]
。因此,String[]
不应被视为Object[]
的子类型,但 Java 规范说它是。因此我们有这样的后果。(请注意,泛型类再次出现类似情况,但这次已 正确 解决。
List<String>
不是List<Object>
的子类型;如果你想拥有一个公共超类型对于这些,您需要List<?>
,它是只读的。数组也应该如此;但事实并非如此。而且由于向后兼容,现在更改它为时已晚。)在您的第一个示例中,
String.split
函数创建了一个String[]
对象。您可以将其放入Object[]
变量中,但对象仍然存在String[]
。这就是它拒绝Integer
值的原因。您必须创建一个新的Objects[]
数组,并复制值。您可以使用System.arraycopy
函数来复制数据,但您无法避免创建新数组。