java.lang.ArrayStoreException:将不正确类型的值分配给 Object [] 数组时 [重复]
Posted
技术标签:
【中文标题】java.lang.ArrayStoreException:将不正确类型的值分配给 Object [] 数组时 [重复]【英文标题】:java.lang.ArrayStoreException: when assigning value with incorrect type to Object[] array [duplicate] 【发布时间】:2018-11-19 23:31:35 【问题描述】:我来自 C 背景。我不能在foo()
中将Object
添加到Object[]
,这对我来说没有意义。
我希望函数 foo
中的代码在运行时工作,但在我尝试执行 strings[0].toLowerCase();
时在 main()
中失败,因为 strings[0]
中的对象不是 String
,但实际上是 @987654330 @ 没有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());
编辑:谢谢大家的回答。感谢@Andy Turner,我在谷歌上搜索了“数组的java协方差”,并遇到了讨论这种行为的this。诀窍是编译器和运行时处理代码的方式非常不同。编译器可以处理代码,运行时不行。
【问题讨论】:
您将StringBuilder
的实例分配给String
的数组。这是不正确的。
我将Object
分配给另一个Object
。这应该是有效的。所有函数foo
说的是“获取此对象引用并将其添加到此数组中”。我同意,稍后,当我将其转换回 String[]
并尝试在 StringBuilder
对象上调用 String
方法时,它应该会失败。
@s5s strings
是 String[]
,而不是 Object[]
。如果你调用foo(...)
,它会向上转换为Object[]
,但是一旦你尝试将一些不是String
的东西存储到这个数组中,你就会得到一个ArrayStoreException
。
ArrayStoreException 非常适合这个。
这是一个很好的例子,说明为什么数组的协方差是一个设计错误。
【参考方案1】:
来自ArrayStoreException
的documentation:
抛出以指示已尝试将错误类型的对象存储到对象数组中。例如,以下代码生成 ArrayStoreException:
Object x[] = new String[3];
x[0] = new Integer(0);
仅仅因为您将String[]
传递给需要Object[]
的方法并不意味着它实际上是Object[]
。因为您创建了String[]
,所以您只能向其中添加String
的实例,而您正在尝试添加StringBuilder
,这没有任何意义。
请注意,如果将String[]
的类型更改为Object[]
,它不会引发异常:
public static void main(String[] args)
Object[] strings = "stringValue" ;
foo(strings, new StringBuilder()); // Perfectly fine
【讨论】:
那么JVM是在做运行时类型检查吗?我希望objects[0] = new StringBuilder()
不会失败,但稍后,如果我尝试在strings[0]
上调用String
方法,我会崩溃,因为指针实际上并未指向String
我对 JVM 的了解还不够多,无法告诉您,但听起来确实如此。鉴于您来自 C 背景,Java 的不同之处在于它通常不会让用户犯这些错误。
检查在the language specification of the simple assignment operator 中描述:“Java 编译器可能能够在编译时证明数组组件的类型为 TC(例如,TC 可能是最终的)。但是如果 Java 编译器无法在编译时证明数组组件的类型为 TC,则必须在运行时执行检查以确保类 RC 与数组的实际类型 SC 的赋值兼容(第 5.2 节)组件。”【参考方案2】:
在运行时评估您的字符串数组实际上是在尝试分配不同的类型。你会是一个ArrayStoreException
,它清楚地表明了
抛出表示试图存储错误的 将对象类型转换为对象数组。例如,以下 代码生成一个 ArrayStoreException:
Object x[] = new String[3];
x[0] = new Integer(0);
接受对象类型作为参数甚至方法/函数的返回值通常不是一个好习惯。它们可能是多态接口,但 Object 处于最高抽象级别,不适合此目的。
【讨论】:
是的,很少需要使用 Object 作为类型参数。我只是不明白为什么在运行时我会遇到将void
指针存储到void
指针数组中的问题。同样,正如我所说,如果我稍后发生崩溃,我会理解,我将这个 void
指针转换为 String
并尝试在演员表上调用 String
方法,如果我这样做会发生@ 987654328@.【参考方案3】:
您正在尝试将对象“StringBuilder”添加到对象“String”的数组中。在某些情况下,如果您要分配 StringBuilder 值,这实际上可能有效,但我不会对此表示担忧,因为我自己从未使用过它。 这是一个很好的阅读:https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html
通常 Java 会为您处理指针,这很难搞砸。
希望能帮到你:)
【讨论】:
我对我使用的类型并不特别在意——我使用 StringBuilder 只是因为。假设我有String[]
并尝试分配class Foo
的实例。
我不懂 C 但在 Java 中你需要严格控制数组中的对象类型。对象有一个名为 Object 的超类,因此您可能会尝试拥有一个“对象”数组并向其中添加一个类。以上是关于java.lang.ArrayStoreException:将不正确类型的值分配给 Object [] 数组时 [重复]的主要内容,如果未能解决你的问题,请参考以下文章