[英]How are expression with logical operators evaluated in Java?
我一直在尝试在 Java 中实现插入排序,并在我的程序中遇到了一个奇怪的错误。 执行插入的while
循环具有以下条件:
while (arr[j] > key && j>=0)
当j<0
时,循环因ArrayIndexOutOfBoundsException
而崩溃。 我花了几个小时试图解决这个问题,但显然改变表达式的顺序解决了这个问题:
while (j >= 0 && arr[j] > key)
这种行为背后的原因是什么?
这是完整的代码:
//Insertion Sort
class Sort {
public int[] sort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int j = i - 1;
int key = arr[i];
while (arr[j] > key && j>=0) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
return arr;
}
}
public class InsertionSort {
public static void main(String[] args) {
System.out.println("THis is it");
int[] test = { 54, 68, 92, 3, 565, 8, 7, 64, 0 };
Sort lort = new Sort();
lort.sort(test);
for (int a : test)
System.out.println(a);
}
}
在尝试访问它之前检查数组索引是否有效很重要。 Java 在右侧之前评估&&
的左侧。 如果您首先检查arr[j] > key
那么您不知道j
是否是有效索引,因为这就是j >= 0
检查的内容。
当您交换订单并写入j >= 0 && array[j] > key
时,如果j
为非负数,它将仅访问array[j]
。 如果为负,则循环立即退出。 永远不会访问无效索引,从而避免异常。
进一步阅读:
当j
达到 -1 时,这:
while (arr[j] > key && j>=0)
评估第一部分并arr[-1]
抛出ArrayIndexOutOfBoundsException
。
当j
达到 -1 时,这:
while (j>=0 &&...)
永远不会尝试访问arr[-1]
,因为这是一个AND
运算符,第一个条件为 false 足以结束评估。 第二个条件无关紧要,因此不在运行时执行。 这样您就可以避免尝试从 Java 数组的 position [-1]
读取;
有人说这是被诅咒的操作,Linus Torvalds 会出现在你的梦想中,因为你生活中的 rest 告诉你 C++ 有多糟糕。
boolean 运算符( &&
和||
)是“短路的”。 这意味着:一旦明确答案已经确定,他们就会立即放弃他们正在做的事情。
特别是,这意味着somethingThatEvalsToFalse && foo
导致foo
甚至根本没有被评估 - false && anything
都是错误的,因此,没有意义。 同样适用于somethingThatEvalsToTrue || foo
somethingThatEvalsToTrue || foo
- true || anything
true || anything
都必然是真的,因此,不需要评估foo
来提供答案。
如果foo
有副作用,这是相关的。 array[j] > key
的副作用是如果j
为负数或超过数组的大小,它将抛出 AIOBEx。 如果发生短路,则不会评估整个表达式。
Java 语言规范涵盖了这一点,但我不建议通过阅读语言规范来学习 java。 这应该是教程中的一章。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.