Java 继续标签已弃用?

发布于 2024-11-19 14:01:47 字数 620 浏览 5 评论 0原文

我有 2 个 for,在嵌套 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
}

谢谢

编辑:
如果我将我的问题改写为:如何在多个嵌套的 for 之间“导航”?这种方法将是“推荐”方法吗?因为这是 SCJP 书中所说的。如果不是……这是否意味着 Katherine SierraBert Bates 是错误的?

编辑2:
为什么不鼓励使用 continue label; ?我想要 OOP 或 Java 的概念或内部工作原理的答案,可能会出现什么问题..

I have 2 fors, after the nested for I have some code which I don't want to execute if a condition is true inside the nested for. If I use break that code would execute, so (as I learned in SCJP) I used continue label; for the outer for.
Is this a deprecated usage of Java ? Old fashioned ? Somebody suggested to use recursion or something else, but for me this is perfectly normal, simple, up-to-date and the perfect way of doing it.

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

Thanks

Edited:
If I rephrase my question as: How can you 'navigate' between multiple nested fors ? This approach would be the 'recommended' way ? because this is what it says in SCJP Book. If not .. would this mean that Katherine Sierra and Bert Bates are wrong ?

Edited2:
Why is continue label; discouraged ? I want an answer of the concepts or inside workings of OOP or Java, what might go wrong ..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

微凉徒眸意 2024-11-26 14:01:47

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

The answer is: it depends. If you find yourself using continue a lot then it might be a sign that your code needs a refactor. However, in the scenario you've given it seems like an OK place to use it.

晌融 2024-11-26 14:01:47

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

例子:

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;
}

I would refactor to make it more readable.

Example:

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;
}
城歌 2024-11-26 14:01:47

我会说它灰心丧气。当替代品更复杂或更容易出错时(即不是改进),它仍然具有有效的用途

I would say its discouraged. It still has valid uses where alternatives are more complex or error prone (i.e. not an improvement)

写下不归期 2024-11-26 14:01:47

参考您的编辑 2,它总是看起来有点不确定,因为它违反了比 OO 更古老的编程正统观念: “结构化编程”。它也带有 goto 的味道,所有优秀的程序员都知道,如果他们在代码中使用了 goto,他们就需要去忏悔。

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

/*
 * 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;
    // Label: <----------------------------------------
    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 to label:  <---------------------------
                    continue outer_loop;
                }
            }
            return i - needleLengthMinus1 - haystackOffset;
        }

        if ((cache & (1 << haystack[i])) == 0) {
            i += needleLengthMinus1;
        }
        i++;
    }
    return -1;
}

With reference to your Edit 2, it is always going to look a bit iffy because it violates an older programming orthodoxy than OO: 'structured programming'. It smacks of goto as well, and all good programmers know they need to go to confession if they let a goto into their code.

There could be some concern that it might make it harder for a compiler to analyse the control flow of a function, but it is the sort of tool that typically gets used for efficiency reasons. For instance, the Apache implementation of java.lang.String uses it in this function that is at least intended to be an optimisation:

/*
 * 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;
    // Label: <----------------------------------------
    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 to label:  <---------------------------
                    continue outer_loop;
                }
            }
            return i - needleLengthMinus1 - haystackOffset;
        }

        if ((cache & (1 << haystack[i])) == 0) {
            i += needleLengthMinus1;
        }
        i++;
    }
    return -1;
}
空气里的味道 2024-11-26 14:01:47

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

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

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

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

Refactor to make it more readable, by placing the inner loop in its own method:

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

The principle: If a method becomes complex enough to require LABELING a block, consider refactoring part of that method into a separate method, such that no label is needed.

Similarly, it is unwise to make methods that are THREE loops deep. Unless the loops are very simple. Even if no labels are needed. Make sure the outermost flow construct (a loop, or an if/else, or a switch) is easy to read, by hiding complexity inside other methods. Even if those methods are only called from one place.

唐婉 2024-11-26 14:01:47

使用名为“成功”的布尔值或类似的值。
阅读和遵循流程要容易得多。 Goto 只能用于错误处理。

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();
    }
}

Use a boolean called 'success' or something like that.
It's much easier to read and to follow the flow. Gotos should only be used for error handling.

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文