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

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

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

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

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

  label1: System.out.println(""); label2: { LabelTest t = new LabelTest(); } 

为了增加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(); 

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

 if (conditionIsTrue) { doSomeProcessing (); if (!resultOfProcessingIsFalse()) { otherwiseDoSomeMoreProcessing(); // More code here that gets executed } } anotherStatement(); 

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

因此,您可以使用除循环之外的标签,甚至可以使用if语句。 例如,这是有效的Java语法(也许你可以想出做这样的事情的理由):

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

如果在这里执行了break ,那么执行会跳到标签所指示的块的末尾,并跳过statementFive()statementSix()

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

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

我认为标签在运营商之前不被禁止的事实,而不是for,while和do可能是规范的java编译器的错误(?!)。 无论如何,它并不是那么重要。 这不会打扰我(个人)。

Java语法基于C语法。

在C中,您可以将标签放在任何位置(不仅仅是在循环上),然后使用goto将执行跳转到该行。 现在, goto没有用Java实现,但保留了标签,以便它们可以与breakcontinue结合使用。

这并不重要,因为这不是标签的标准用途。 使用带有continuebreak标签已经够糟糕了(大多数情况下)。 自由使用它们也没用。

请参阅JLS中的Lable