我理解ArrayStoreException是什么。我的问题是:为什么不被编译器捕获?
这可能是一个奇怪的例子,但是你说这样做:
HashMap[] h = new LinkedHashMap[4];
h[0] = new PrinterStateReasons();
为什么编译器不能识别出这是无效的?
答案 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。