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

-1 java break while-loop

我有以下方法:

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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

有趣的是,它并非总是发生.有时我的程序运行正常,有时会出现上述问题.就像提出的一个问题一样.

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

T.J*_*der 5

一个无向的break只会突破它出现的最里面的循环.例如,break这里:

while (condition1) {
    while (condition2) {
        if (condition3) {
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

如果你需要突破外部循环,那么可能值得做一些重构,但是如果你真的需要你可以标记外部循环然后使用定向中断:

    outer: while (condition1) {
//  ^^^^^----- the label
        while (condition2) {
            if (condition3) {
                break outer;
// Directed ----------^^^^^
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

该函数是递归的,调试递归函数可能有点令人困惑,虽然递归不在这些内部循环中,所以我不希望它在那里考虑因素.

  • @MonkeyDeKing:尊重,确实如此.如果您认为没有,您需要生成一个我们可以用来独立验证它的[mcve],但请记住Pragmatic Progammer的建议:[`select`没有被破坏](https://pragprog.com /在语用程序员/提取物/提示).也不是'休息'.也许这种递归让你感到困惑?虽然它不会出现在你说的循环中...... (4认同)