在没有"循环"的java中使用标签

szy*_*ond 14 java loops labels

我一直以为标签必须只用于循环,但似乎不是.给这样的代码:

public class LabelTest {
    public static void main(String[] args) {
        label1: System.out.println("");
        label2: LabelTest t = new LabelTest();  
    }                                               
}
Run Code Online (Sandbox Code Playgroud)

当标记为"label1"的编译行编译时,"label2"处的代码会出错.为什么?为什么我要标记不是"循环"的语句?

Mic*_*rdt 18

你得到一个错误,因为标签不能应用于变量声明,这就是语法语法的定义方式(标签只能在a之前Statement,a LocalVariableDeclarationStatement不在a之前Statement).原因可能是它可能导致关于变量范围的混淆.这有效:

    label1: System.out.println("");
    label2: { LabelTest t = new LabelTest(); }
Run Code Online (Sandbox Code Playgroud)

  • 我认为问题是*为什么*是这样定义的语言?为什么不在`for`,`while`和`do`语句之前允许标签? (3认同)

Mic*_*utz 7

为了增加Michael Borgwardt的答案,你可以为了方便而做这样的事情(我刚刚在阅读Java rt.jar源代码时发现了这一点):

BlockSegment:
if (conditionIsTrue) {
    doSomeProcessing ();
    if (resultOfProcessingIsFalse()) break BlockSegment;
    otherwiseDoSomeMoreProcessing();
    // These lines get skipped if the break statement
    // above gets executed
}
// This is where you resume execution after the break
anotherStatement();
Run Code Online (Sandbox Code Playgroud)

现在,这在逻辑上等同于:

if (conditionIsTrue) {
    doSomeProcessing ();
    if (!resultOfProcessingIsFalse()) {
        otherwiseDoSomeMoreProcessing();
        // More code here that gets executed
    }
}
anotherStatement();
Run Code Online (Sandbox Code Playgroud)

但是,你可以跳过一些额外的括号(和括号附带的缩进).也许它看起来更干净(在我看来确实如此),并且在某些地方,这种编码风格可能适合并且不那么令人困惑.

因此,您可以使用标签,而不仅仅是循环,甚至超出if语句.例如,这是有效的Java语法(也许你可以想出做这样的事情的原因):

statementOne();
statementTwo();
BlockLabel: {
    statementThree();
    boolean result = statementFour();
    if (!result) break BlockLabel;
    statementFive();
    statementSix();
}
statementSeven();
Run Code Online (Sandbox Code Playgroud)

如果break被在此执行,则执行跳转到由标签标记的代码块的结束,statementFive()statementSix()得到跳过.

if当你在必须跳过的区块内有块时,这种风格的有用性(没有语句)变得更加明显. 一般来说,你可以通过足够聪明地使用循环来完成所有事情.但是,在某些情况下,没有循环的标签可以更容易地读取代码.例如,如果您需要按顺序检查参数,则可以执行此操作或抛出异常.它最终成为代码清洁和个人风格的问题.


Ale*_*exR 1

它无法编译。好问题!我刚刚玩了一下你的代码片段。编译器似乎希望在标签之后调用方法或运算符。此时不允许分配。

我认为除了 for、while 和 do 之外的运算符之前不禁止标签这一事实可能是规范的 java 编译器的一个错误(?!)。无论如何,这并不那么重要。这并不困扰我(个人)。

  • 这不是赋值,而是初始化。它的中断不是因为初始化,而是因为变量声明。 (2认同)