Java 'break' 语句有时不起作用,为什么?

Java ‘break’ statement sometimes not work, Why?

我有以下方法:

public int quickFind (int[] nums, int lo, int hi) {
    if (lo >= hi)
        return -1;

    int gard = nums[lo];
    int i = lo + 1, j = hi + 1;

    while (true) {

        while (nums[++i] < gard) {
            if (i == hi) {
                System.out.println("break   " + i + " / " + hi + " ->" + (i == hi));
                break;
            }
        }

        while (gard < nums[--j]) {
            if (j == lo)
                break;
        }

        if (i > j)
            break;

        if (nums[i] == gard)
            return nums[i];
        if (nums[j] == gard) 
            return nums[j];

        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    nums[lo] = nums[j];
    nums[j] = gard;

    return 1 + quickFind(nums, lo, j - 1) + quickFind(nums, j + 1, hi);
}

然后我构建了一个随机数组,例如 [3 4 2 4 1 5] 来测试我的方法。但是,第 13 行的 break 语句似乎不起作用,并抛出异常消息 "java.lang.ArrayIndexOutOfBoundsException: 6".

所以,我设置断点调试第13行的break语句和第11行的if条件,简直不敢相信自己的眼睛。 'break' 不起作用。

有趣的是,它并不总是发生。有时我的程序运行良好,有时会出现上述问题。就像一个 question that has been raised.

谁能告诉我为什么?为什么会这样?

因为在某些情况下你 break 跳出内部 while 循环,而其他情况你只是 break 跳出外部 while 循环.基本上它们在不同的范围内被调用。

无向 break 只会跳出它所在的最内层循环。例如,此处的 break

while (condition1) {
    while (condition2) {
        if (condition3) {
            break;
        }
    }
}

...突破 while (condition2) 而不是 while (condition1).

如果你需要跳出外循环,可能值得做一些重构,但如果你真的需要,你可以标记外循环,然后使用定向休息:

    outer: while (condition1) {
//  ^^^^^----- the label
        while (condition2) {
            if (condition3) {
                break outer;
// Directed ----------^^^^^
            }
        }
    }

break 将突破两个 while (condition1)(根据定义,它会突破 while (condition2))。


这是该代码中 breaks 的细分(无双关语)以及它们打破的循环:

public int quickFind (int[] nums, int lo, int hi) {
    if (lo >= hi)
        return -1;

    int gard = nums[lo];
    int i = lo + 1, j = hi + 1;

    while (true) { // *** Loop 1

        while (nums[++i] < gard) { // *** Loop 2
            if (i == hi) {
                System.out.println("break   " + i + " / " + hi + " ->" + (i == hi));
                break; // *** Breaks loop 2
            }
        }

        while (gard < nums[--j]) { // *** Loop 3
            if (j == lo)
                break; // *** Breaks loop 3
        }

        if (i > j)
            break; // *** Breaks loop 1

        if (nums[i] == gard)
            return nums[i];
        if (nums[j] == gard) 
            return nums[j];

        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    nums[lo] = nums[j];
    nums[j] = gard;

    return 1 + quickFind(nums, lo, j - 1) + quickFind(nums, j + 1, hi);
}

函数是递归的,调试递归函数可能有点混乱,尽管递归不在任何一个内部循环中,所以我不希望它考虑进去。

条件(i==hi)在hi = 6, lo = 5时不会被检查,而是抛出OutOfBoundsException请在调试器中检查它们的值

  while (nums[++i] < gard) {
        if (i == hi) {
            System.out.println("break   " + i + " / " + hi + " ->" + (i == hi));
            break;
        }
    }