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

发布于 2024-10-18 09:56:07 字数 356 浏览 8 评论 0原文

我一直认为标签必须仅与循环一起使用,但似乎并非如此。给出这样的代码:

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

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

I always thought that the labels must be used only with loops but it seems not. Giving such code:

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

When compiled line labeled "label1" compiles but the code at "label2" gives errors. Why's that? And why would I want to label statements which are not "loops"?

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

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

发布评论

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

评论(6

老子叫无熙 2024-10-25 09:56:07

您会收到错误,因为标签无法应用于变量声明,这就是 语言语法已定义(标签只能在Statement之前,并且LocalVariableDeclarationStatement不是Statement)。原因可能是它可能会导致变量范围的混乱。这有效:

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

You get an error because a label cannot be applied to variable declarations, that's just how the language grammar is defined (a label can only precede a Statement, and a LocalVariableDeclarationStatement is not a Statement). The reason is probably that it could cause confusion concerning variable scope. This works:

    label1: System.out.println("");
    label2: { LabelTest t = new LabelTest(); }
陈甜 2024-10-25 09:56:07

为了补充 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 在此处执行,则执行跳到由label,并且 statementFive()statementSix() 被跳过。

当您必须跳过块中的块时,这种样式(没有 if 语句)的有用性变得更加明显。 一般来说,您可以通过足够聪明地使用循环来完成所有事情。但是,在某些情况下,不带循环的标签可以更轻松地阅读代码。例如,如果您需要顺序检查参数,您可以这样做或抛出异常。这最终是代码整洁度和个人风格的问题。

To add to Michael Borgwardt's answer, you can do things like this for convenience (I just discovered this the other day while reading through the Java rt.jar source code):

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

Now, this is logically equivalent to:

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

But, you get to skip some of the extra braces (and indentations that come with braces). Perhaps it looks cleaner (it does in my opinion), and there are some places where this style of coding may be appropriate and less confusing.

So, you may use labels beyond just loops, and even beyond if statements. For example, this is valid Java syntax (and maybe you could conjure up a reason to do something like this):

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

If the break gets executed here, then execution skips to the end of the block denoted by the label, and statementFive() and statementSix() get skipped.

The usefulness of this style (without an if statement) becomes more evident when you have blocks within blocks where you must skip around. In general, you can accomplish everything with smart enough use of loops. However, there are a few cases where labels without loops make for easier reading of code. For example, if you need to sequentially check parameters, you may either do this or throw an exception. It ends up being a matter of cleanliness of code and personal style.

浪菊怪哟 2024-10-25 09:56:07

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

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

It does not compile. Good question!
I have just played a little bit with your code snippet. It seems that compiler expects method call or operator after label. It does not allow assignment at this point.

I think that the fact that label is not forbidden before operators other than for, while and do is probably a bug (?!) of java compiler of specification. Anyway it is not so critical. It does not bother me (personally).

爱的十字路口 2024-10-25 09:56:07

Java语法是基于C语法的。

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

这并不重要,因为无论如何这都不是标签的标准使用。使用带有 continuebreak 的标签已经够糟糕的了(大多数时候)。随意使用它们也是没有用的。

Java syntax is based on C syntax.

In C you can put a label anywhere (not just on loops) and then use goto to jump the execution to that line. Now, goto wasn't implemented in Java, but labels were left so that they can be used in combination with break or continue.

It's not that important since this isn't a standard use of labels anyway. Using labels with continue or break is bad enough (most of the times). Using them freely is also useless.

时光清浅 2024-10-25 09:56:07

我回答这个问题有点晚了。无论如何,

label2: LabelTest t = new LabelTest(); ->不起作用,因为它是声明性声明,因为上面的大多数评论都声明相同。要使其工作,只需执行以下操作:

label2: new LabelTest(); // 工作正常

I am little late to answer this. Anyway,

label2: LabelTest t = new LabelTest(); -> Doesn't work because it is a declarative statement, as most of the above comments state the same. To make it work just do the following:

label2: new LabelTest(); // works fine

你的笑 2024-10-25 09:56:07

请参阅 JLS 中的标签

Refer to Lable in JLS

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