【问题标题】:Why does adding an Integer to a String array in Java not generate a compilation error?为什么在 Java 中将 Integer 添加到 String 数组不会产生编译错误?
【发布时间】:2012-07-01 17:38:43
【问题描述】:

为什么我尝试将Integer 添加到声明为Object[] 但实例化为String[] 的Java 数组不会产生编译错误?

Object[] ob = new String[1];
ob[0] = new Integer(1); // this shouldn’t compile but it does!

当我运行它时,我得到一个运行时异常,而不是一个(非常喜欢的)编译时错误!这是正确的行为吗?我不应该得到一个编译时错误吗?

【问题讨论】:

  • ob 是一个Object[]IntegerObject 的子类。所以这应该编译得很好。也许您想将ob 声明为String[]
  • #HovercraftFullOfEels 你说的写得不好的代码是真的,但在其他语言中,C++ 会想到你受到编译器的保护,不会写出这样的废话。顺便提一下,这是一个简单的例子。在现实世界的程序中,您不可能同时看到所有代码。你怎么知道你是否为正确的容器分配了正确的类型?
  • @smallB:除了将变量声明为可能的最通用类型之外,我不知道答案。
  • 我不明白为什么这个问题被关闭了。这是一个关于 Java 语义陷阱的完全合理的问题。可能让您感到困惑的要点是引用数组的运行时类型 (String[]) 与数组变量的编译时类型 (Object[])。编译器只强制你放入数组的内容与引用它的数组变量的静态类型兼容。
  • 我同意@Marko,这是一个关于 Java 的有效问题,澄清这些原则只能帮助我们所有人,我已投票重新开放并投票赞成该问题。我看到关闭它的唯一原因是某处是否存在完全相同的副本。

标签: java


【解决方案1】:

这是 Java 设计人员做出的选择:String[] 扩展了 Object[],但除了 String 之外,您不能将任何其他内容添加到 concrete 类型为 String[] 的数组中没有运行时异常。

他们可能使以下内容无效:

Object[] ob = new String[1];

因为它有效地允许将任何类型的对象添加到数组中而不会出现任何编译器错误(如您所见),这是完全正常的,因为整数 is 是一个对象,而 compile-time 数组的类型是Object[]

他们没有为数组做出这个选择,但他们为泛型集合做了这个选择:

List<Object> ob = new ArrayList<String>();

生成编译器错误,因为List&lt;String&gt; 没有扩展List&lt;Object&gt;。集合通常比数组更受欢迎,因为它们更安全,并提供更多功能。

【讨论】:

  • 在我看来,OP 的实际混淆在于数组的编译时与运行时类型。他认为编译器应该防止将Integer 放入String 数组中(与数组类型协方差无关)。
  • 是的。我已经编辑了我的答案以使其更清楚。谢谢你的建议。
【解决方案2】:

您可能需要考虑的要点是引用数组的运行时类型 (String[]) 与数组变量的编译时类型 (Object[])。编译器仅强制您放入数组的内容与引用它的数组变量的静态类型兼容。这个例子使它脱颖而出:

String[] strs = new String[1]; 
Object[] objs = strs; 
strs[0] = new Integer(1); /* error, says the compiler! */ 
objs[0] = new Integer(1); /* fine by me, says the compiler! */

现在,您理所当然地应该为您的第一行感到不安:Object[] ob = new String[1];,这意味着 String[]Object[] 的赋值兼容——换句话说,它的子类型。这与 CS 中众所周知的事实相反,即容器类型在其元素的类型上是逆变的。为什么Java不是这样?我曾经读过一个帐户,其中有人问 James Gosling,他回答说他们知道事实,但想要一种简单的方法让 Java 方法能够接受任何类型的数组(通过 Object[] 类型)。这源于对 Java 成为“蓝领语言”的要求,而不是陷入类型理论的精确性,这会带来他们自己的心理包袱。见证泛型的 &lt;? super String&gt; 和 Scala 的协变/逆变位置规则。

【讨论】:

    猜你喜欢
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2021-08-18
    • 1970-01-01
    • 2023-03-22
    • 2012-01-03
    • 1970-01-01
    相关资源
    最近更新 更多