代码之家  ›  专栏  ›  技术社区  ›  Mrak Vladar

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

  •  0
  • Mrak Vladar  · 技术社区  · 3 年前

    我一直在尝试在Java中实现插入排序,在我的程序中遇到了一个奇怪的错误。这个 while 执行插入的循环具有以下条件:

    while (arr[j] > key && j>=0)
    

    循环以一个 ArrayIndexOutOfBoundsException 什么时候 j<0 。我花了几个小时试图解决这个问题,但显然改变表达式的顺序解决了这个问题:

    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);
        }
    }
    
    3 回复  |  直到 3 年前
        1
  •  4
  •   John Kugelman Michael Hodel    3 年前

    在尝试访问数组索引之前,检查数组索引是否有效非常重要。Java计算数组索引的左侧 && 在右手边之前。如果你检查 arr[j] > key 首先,你不知道 j 是一个有效的索引,因为这就是 j >= 0 检查。

    当你交换订单并写 j >= 0 && array[j] > key 那么它只能访问 array[j] 如果 j 是非负的。如果为负,则循环立即停止。无效索引永远不会被访问,从而避免了异常。

    进一步阅读:

        2
  •  1
  •   rzwitserloot    3 年前

    布尔运算符( && || )是“短路”。这意味着:一旦答案明确,他们就会立即放弃他们正在做的事情。

    特别是,这意味着 somethingThatEvalsToFalse && foo 结果在 foo 甚至根本没有被评估过- false && anything 是假的,因此没有意义。同样适用于 somethingThatEvalsToTrue || foo - true || anything 必然为真, foo 不需要评估来提供答案。

    如果 foo 有副作用。 array[j] > key 如果发生以下情况,它会抛出AIOBEx,这是一种副作用 j 为负或超过数组大小。如果短路开始,则不会计算整个表达式。

    Java语言规范涵盖了这一点,但我不建议通过阅读语言规范来学习Java。这应该是教程中的一章。

        3
  •  1
  •   aran    3 年前
    • 什么时候? j 点击-1,这个:

      while (arr[j] > key && j>=0)

      评估第一部分和 arr[-1] 投掷a ArrayIndexOutOfBoundsException .


    • 什么时候? j 点击-1,这个:

      while (j>=0 && ...)

      永远不会尝试访问 arr[-1] ,因为这是一个 AND 运算符和第一个条件为假就足以结束评估。第二个条件无关紧要,因此不会在运行时执行。这样你就可以避免试图从位置上阅读 [-1] Java数组;

      有人说这是诅咒,Linus Torvalds将在你的余生中出现在你的梦想中 有多糟糕C++ 是。