19

我有 2 个 fors,在嵌套 for 之后,如果嵌套 for 中的条件为真,我不想执行一些代码。如果我使用 break 代码将执行,所以(正如我在 SCJP 中学到的)我使用continue label;了外部 for。这是 Java 的弃用用法吗?老式的?有人建议使用递归或其他方法,但对我来说,这是完全正常、简单、最新且完美的做法。

here:
for (bla bla) {
   for (bla bla) {
      if (whatever) continue here;
   }
// some code I don't want to execute if whatever is true
}

谢谢

编辑:
如果我将我的问题改写为:您如何在多个嵌套 fors 之间“导航”?这种方法将是“推荐”的方式吗?因为这是 SCJP Book 中所说的。如果不是..这是否意味着Katherine Sierra并且Bert Bates是错误的?

编辑2:
为什么continue label;气馁?我想要一个关于 OOP 或 Java 的概念或内部工作原理的答案,可能会出什么问题..

4

6 回答 6

8

答案是:视情况而定。如果您发现自己使用continue了很多,那么这可能表明您的代码需要重构。但是,在您给出的场景中,它似乎是一个可以使用它的地方。

于 2011-07-11T12:46:53.463 回答
8

我会重构以使其更具可读性。

例子:

if (!checkWhatever()) {
    // some code I don't want to execute if whatever is true
}
boolean checkWhatever() {
    for (bla bla) {
       for (bla bla) {
          if (whatever) return false;
       }
    }
    return true;
}
于 2011-07-11T12:50:08.797 回答
5

我会说它气馁。在替代方案更复杂或容易出错(即不是改进)的情况下,它仍然具有有效用途

于 2011-07-11T12:46:10.487 回答
3

参考您的编辑 2,它总是看起来有点不确定,因为它违反了比 OO 更古老的编程正统观念:“结构化编程”(参见http://en.wikipedia.org/wiki/Structured_programming)。它也带有 goto 的味道,所有优秀的程序员都知道,如果他们在代码中加入了 goto,他们需要承认。

可能有人担心它可能会使编译器更难分析函数的控制流,但它是一种通常出于效率原因而使用的工具。例如,Apache 的实现java.lang.String在这个函数中使用它,至少是为了优化:

/*
 * An implementation of a String.indexOf that is supposed to perform
 * substantially better than the default algorithm if the "needle" (the
 * subString being searched for) is a constant string.
 *
 * For example, a JIT, upon encountering a call to String.indexOf(String),
 * where the needle is a constant string, may compute the values cache, md2
 * and lastChar, and change the call to the following method.
 */
@SuppressWarnings("unused")
private static int indexOf(String haystackString, String needleString,
        int cache, int md2, char lastChar) {
    char[] haystack = haystackString.value;
    int haystackOffset = haystackString.offset;
    int haystackLength = haystackString.count;
    char[] needle = needleString.value;
    int needleOffset = needleString.offset;
    int needleLength = needleString.count;
    int needleLengthMinus1 = needleLength - 1;
    int haystackEnd = haystackOffset + haystackLength;
    outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
        if (lastChar == haystack[i]) {
            for (int j = 0; j < needleLengthMinus1; ++j) {
                if (needle[j + needleOffset] != haystack[i + j
                        - needleLengthMinus1]) {
                    int skip = 1;
                    if ((cache & (1 << haystack[i])) == 0) {
                        skip += j;
                    }
                    i += Math.max(md2, skip);
                    continue outer_loop;
                }
            }
            return i - needleLengthMinus1 - haystackOffset;
        }

        if ((cache & (1 << haystack[i])) == 0) {
            i += needleLengthMinus1;
        }
        i++;
    }
    return -1;
}
于 2012-04-19T22:29:42.997 回答
1

通过将内部循环放在自己的方法中,重构使其更具可读性:

for (bla bla) {   
  DoStuff();
}
void DoStuff() {
  for (bla bla) {
    if (whatever) return;
  }
  // some code to execute when whatever is false.
}

原则:如果方法变得复杂到需要对块进行标记,请考虑将该方法的一部分重构为单独的方法,这样就不需要标记。

同样,使方法具有三个循环深度是不明智的。除非循环非常简单。即使不需要标签。通过将复杂性隐藏在其他方法中,确保最外层的流结构(循环、if/else 或开关)易于阅读。即使这些方法只从一个地方调用。

于 2013-11-27T21:31:19.000 回答
0

使用一个名为“成功”的布尔值或类似的东西。它更容易阅读和遵循流程。Gotos 应该只用于错误处理。

boolean success = true;
for(int outer = 0; (outer <= outerLimit) && sucess; outer++)
{
    for(int inner = 0; (inner <= innerLimit) && success; inner++)
    {
        if( !doInnerStuff() )
        {
            success = false;
        }
    }

    if( success )
    {
        success = doOuterStuff();
    }
}
于 2014-07-17T17:10:27.000 回答