为什么Java编译器不能捕获ArrayStoreExceptions?

时间:2011-12-04 22:27:16

标签: java exception

我理解ArrayStoreException是什么。我的问题是:为什么不被编译器捕获?

这可能是一个奇怪的例子,但是你说这样做:

    HashMap[] h = new LinkedHashMap[4];
    h[0] = new PrinterStateReasons();

为什么编译器不能识别出这是无效的?

4 个答案:

答案 0 :(得分:4)

因为你给编译器提供的信息允许你正在做的事情。它只是运行时状态无效。您的h变量被声明为HashMap[],这意味着就h而言,实现HashMap的任何内容都是有效元素。 PrinterStateReasons实现HashMap,因此h[0] = new PrinterStateReasons();是完全有效的陈述。同样,由于LinkedHashMap实现HashMap,语句HashMap[] h = new LinkedHashMap[4];是完全有效的语句。只有在运行时,您才会尝试将PrinterStateReasons对象存储为LinkedHashMap数组中的元素,这是您无法执行的,因为它不是赋值兼容的。

你给出的两个陈述是连续的,但当然普遍的现实要复杂得多。考虑:

HashMap[] h = foo.getHashMapArray();
h[0] = new PrinterStateReasons();

// ... elsewhere, in some `Foo` class -- perhaps compiled
// completely separately from the code above, perhaps
// even by a completely different team and even a different
// compiler --  and only combined with the code above at runtime...

public HashMap[] getHashMapArray() {
    return new LinkedHashMap[4];
}

答案 1 :(得分:0)

当您使用更通用的类型数组引用特定类型数组时,编译器无法捕获的内容:

String[] s = new String[10];
Object[] o = s;
o[0] = new Integer(5);

编译器无法检测到它,因为从变量声明中无法知道数组的实际类型。

请注意,通用集合不会出现此问题,因为虽然String []也是Object [],但List<String>不是List<Object>。更喜欢集合而不是数组的另一个原因。

答案 2 :(得分:0)

Java语言规范说这是有效的程序。将其标记为错误的编译器未实现规范,因此不是兼容的Java编译器。不合规编译器的真正危害在于它导致人们编写不可移植的源代码;例如用一个编译器编译而不是另一个编译器。

编译器可以合法做的最好的事情是警告你代码将始终抛出异常。例如,某些编译器会警告您将始终抛出空指针异常。我猜他们不会在数组索引中执行此操作,因为分析更复杂,并且错误的发生频率较低。

答案 3 :(得分:0)

好吧,我认为智能编译器能够静态分析h除了第2行的LinkedHashmap []之外别无其他。

但如果没有(可能相当复杂的分析,也许不是这种简单的情况),编译器无法真正知道分配给h的内容。您可以将PrinterStateReasons分配给HashMap,而不是分配给LinkedHashMap。