java.lang.ArrayStoreException:将类型不正确的值分配给 Object[] 数组时

s5s*_*s5s 5 java

我来自 C 背景。我不能Object在 aObject[]中添加 an对我来说没有意义foo()

我希望函数中的代码在foo运行时工作但在main()我尝试时失败,strings[0].toLowerCase();因为中的对象strings[0]不是 aString但实际上是StringBuilder没有toLowerCase(). 在一天结束时,我将一个指针存储到一个指针数组中,并且该行objects[0] = other不应无效。很明显,我对 java 的理解是错误的(但我目前是一个相当新的人)。

class Main {

    static void foo(Object[] objects, Object other) {
        objects[0] = other;
    }
    public static void main(String[] args) {
        String[] strings = { "stringValue" };
        foo(strings, new StringBuilder());
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:谢谢大家的回答。我GOOGLE了感谢@Andy特纳“数组的java的协方差”,并碰上了其中讨论了这种行为。诀窍在于编译器和运行时对代码的处理非常不同。编译器对代码很好,运行时不是。

Jac*_* G. 4

来自以下文档ArrayStoreException

抛出该异常表示尝试将错误类型的对象存储到对象数组中。例如,以下代码生成 ArrayStoreException:

Object x[] = new String[3];
x[0] = new Integer(0);
Run Code Online (Sandbox Code Playgroud)

仅仅因为您将 a 传递String[]到需要 an 的方法Object[]并不意味着它实际上是一个Object[]。因为您创建了 a String[],所以只能String向其中添加 的实例,并且您尝试添加 a StringBuilder,这是没有意义的。

请注意,如果将类型更改为String[]to ,它不会引发异常Object[]

public static void main(String[] args) {
    Object[] strings = { "stringValue" };
    foo(strings, new StringBuilder()); // Perfectly fine
}
Run Code Online (Sandbox Code Playgroud)

  • 检查在[简单赋值运算符的语言规范](https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.26.1)中描述:“ Java 编译器可能能够在编译时证明数组组件将完全是 TC 类型(例如,TC 可能是最终的)。但是如果 Java 编译器无法在编译时证明数组组件将是 TC 类型准确地说,那么必须在运行时执行检查,以确保类 RC 与数组组件的实际类型 SC 分配兼容(第 5.2 节)。” (2认同)