ace*_*azz 3 java arrays exception-handling exception runtimeexception
假设我们有以下程序:
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); }
}
}
Run Code Online (Sandbox Code Playgroud)
基于Java文档:
抛出以指示已尝试将错误类型的对象存储到对象数组中.
我在这里读到了
创建数组时,它会记住它要存储的数据类型.
如果数组记住它包含的数据类型,则意味着它知道它包含的数据类型.但是我发布的代码片段是正确编译的,所以在编译时,数组显然不知道包含什么类型.
我的问题是:
为什么ArrayStoreException
只在运行时抛出?
编译器缺少哪些信息来实现该分配是不可能的?
ArrayStoreException
抛出?如果数组记住它包含的数据类型,则意味着它知道它包含的数据类型.
在执行时,是......就像在执行时一样,对象的类型是已知的:
Object x = "foo";
// The compiler won't let you call x.length() here, because the variable
// x is of type Object, not String.
Run Code Online (Sandbox Code Playgroud)
另一种方法是使非常多的数组赋值隐式抛出一个已检查的异常.那太糟糕了 - 类似于NullPointerException
检查.
编译器缺少哪些信息来实现该分配是不可能的?
正如你所见,数组是协变的.当编译器看到的转让成Fruit[]
的Apple
,它不能知道什么实际数组的类型将是.如果是,Fruit[]
或者Apple[]
,那没关系.如果不是这样的Orange[]
话.该信息仅在执行时出现 - 再次,就像编译器不知道表达式是否绝对不为空.
是否存在此类代码正确的情况,因此不会抛出ArrayStoreException?
好吧,如果你有一个具有最终类的编译时元素的数组,那么你就不能有任何较低的方差.例如:
public void foo(String[] array) {
array[0] = "x";
}
Run Code Online (Sandbox Code Playgroud)
这可能会因为array
存在null
或空而引发异常,但它永远不会抛出异常ArrayStoreException
,因为它String
是最终的.实施永远不会是一个SubclassOfString[]
.