假设我们有以下程序:
class Fruit {}
class Apple extends Fruit {}
class Jonathan extends Apple {}
class Orange extends Fruit {}
public class Main {
public static void main(String[] args) {
Fruit[] fruit = new Apple[10];
try {
fruit[0] = new Fruit(); // ArrayStoreException
fruit[0] = new Orange(); // ArrayStoreException
} catch(Exception e) { System.out.println(e); }
}
}基于Java文档
引发,以指示已尝试将错误类型的对象存储到对象数组中。
我读过这里
创建数组时,它会记住要存储的数据类型。
如果数组记住它包含的数据类型,就意味着它知道它包含的数据类型。但是我发布的片段是正确编译的,所以在编译时数组显然不知道包含什么类型。
我的问题是:
ArrayStoreException?ArrayStoreException吗?发布于 2016-07-15 09:18:23
创建数组时,它会记住要存储的数据类型。
数组“只记得”它在运行时实际包含的类型。
首先,将数组声明为果树数组。
然后创建数组,在本例中是Apple的数组。
创建是在运行时进行的,但编译器的设计仅用于验证数组是否仅被指定为它声明为的类型的对象。在运行时,有很多事情可以发生。
考虑以下代码:
class Fruit {}
class Apple extends Fruit {}
class Jonathan extends Apple {}
class Orange extends Fruit {}
public class Main {
public static void main(String[] args) {
Fruit[] fruit = new Apple[10];
boolean alt = (Math.random() < 0.5);
try {
fruit[0] = fruitFactory(alt);
} catch(Exception e) { System.out.println(e); }
}
private static Fruit fruitFactory(boolean apple) {
if (apple) {
return new Apple();
} else {
return new Orange();
}
}
}该代码与您的代码相同,只是fruitFactory方法为水果分配了一个值。编译器无法判断布尔alt是true还是false。
编译器缺少哪些信息来意识到分配是不可能的?
如前所述,编译器无法判断分配是否可行。
在任何情况下,这些代码都是正确的,因此不会抛出ArrayStoreException吗?
是的,在以上代码中的50 %的情况下。您必须验证分配的对象是否与数组相同,或者捕获异常。
发布于 2016-07-15 08:20:14
如果数组记住它包含的数据类型,就意味着它知道它包含的数据类型。
在执行的时候,是的..。就像在执行时一样,对象的类型是已知的:
Object x = "foo";
// The compiler won't let you call x.length() here, because the variable
// x is of type Object, not String.另一种方法是进行非常多的数组赋值,隐式抛出一个检查异常。这将是可怕的-类似于让NullPointerException检查。
编译器缺少哪些信息来意识到分配是不可能的?
正如您所看到的,数组是协变量的。当编译器看到一个赋值到一个Fruit[]的Apple中时,它无法知道该数组的实际类型。如果是Fruit[]或Apple[],那就好了。如果是Orange[],那就不是。该信息仅在执行时才出现,就像编译器不知道表达式是否为null一样。
在任何情况下,这些代码都是正确的,因此不会抛出ArrayStoreException吗?
如果您有一个数组,其中包含最后一个类的编译时元素,那么就不可能有任何较低的方差。例如:
public void foo(String[] array) {
array[0] = "x";
}这可能会引发由于array是null或空而引发的异常,但是它不会抛出ArrayStoreException,因为String是最终的。实现不可能是SubclassOfString[]。
发布于 2016-07-15 08:21:12
出于与ClassCastException相同的原因,这是一个运行时异常。并不总是能够在编译时判断该类型是否符合您的预期。
考虑一下这个例子:
void method1() {
Fruit[] fruits = getFruits();
fruits[0] = new Orange();
}
Fruit[] getFruits() {
if (someCondition) {
return new Apple[5];
} else {
return new Orange[5];
}
}编译器无法知道当您调用someCondition时getFruits()将处于什么状态。因此出现了运行时异常。
https://stackoverflow.com/questions/38391161
复制相似问题