有人可以向我解释为什么ArrayIndexOutOfBoundsException
是运行时异常而不是编译时错误?
在明显的情况下,当索引为负数或大于数组大小时,我不明白为什么它不能成为编译时错误。
已编辑:尤其是在编译时已知数组的大小甚至索引时,例如int[] a = new int[10]; a[-1]=5;
这应该是编译错误。
答案 0 :(得分:4)
可以仅在运行时定义数组的大小(例如,最简单的情况,如果数组的大小取决于用户输入)。
因此,在编译时检查数组的访问而不实际知道它的边界(大小)是不可能在编译时检查的。
答案 1 :(得分:3)
因为无法在编译时始终检测到它。
答案 2 :(得分:1)
输入a[-1] = 5;
只是新手会做的事情(正如Richard Tingle所说)。因此,仅为此类错误更新语言标准是不值得的。更有趣的情况是a[SOME_CONSTANT] = 5;
其中SOME_CONSTANT
被定义为static final int SOME_CONSTANT = -1;
(或某些表达式仅涉及计算-1
的常量)。但是,即使这样,如果编译器将此标记为错误,它也可能会遇到程序员已将a[SOME_CONSTANT] = 5;
放入已检查该常量负值的if
语句中的情况。 (我在这里假设SOME_CONSTANT
是一个常量,如果应用程序的需求发生变化,其值可能会改变。)因此,从理论上讲,语言可能会使编写数组索引操作成为非法那可能不会成功,有充分的理由不这样做。
P.S。这是一个真正的问题。 Ada语言确实对静态表达式进行了一些编译时检查,这些表达式无法成功,但是它没有检查这种情况,并且在过去几周内已经讨论过它是否应该,或者是否应该允许编译器(但不是必需的)拒绝具有已知失败的数组索引的程序。
答案 3 :(得分:0)
使用指针时,如果您正确保留了将要访问的内存位置,则可能有负索引并且没有错误。这是一个例子。使用低级编程语言时,像这样的事情很常见,但是在高级语言中它们没有多大意义,至少对我来说是这样。
int arr[10];
int* p = &arr[2];
int x = p[-2]; // valid: accesses arr[0]
如果您尝试这样做:
arr[-5] //you will access and invalid block of memory, this why you get the error.
这可能会带来非常有用和有趣的信息:
http://www-ee.eng.hawaii.edu/~tep/EE160/Book/chap7/subsection2.1.3.2.html
答案 4 :(得分:0)
在编译时无法检查所有索引,因为它们可以是变量,其值可以在运行时更改。如果您有array[i]
和i
是读取文件的结果,则可以在执行程序时评估i
。即使您使用变量,请记住您可以重新分配您的阵列以更改其容量。同样,这只能在运行时检查。
查看此问题以获取更多信息:Runtime vs Compile time。
答案 5 :(得分:0)
除了同意在编译时无法检查数组大小这一事实之外,我想在数组大小的限制上添加另一个注释,预计它将在原始范围内int
:
// This compiles, because the size evaluates to an integer.
int[] array = new int[Integer.MAX_VALUE + 1];
// This doesn't compile.
int[] array = new int[Long.MAX_VALUE];
这个错误是因为length
字段(int
)是特殊Java对象的数组。