繁体   English   中英

如何在 Java 中评估带有逻辑运算符的表达式?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM