【问题标题】:Is a label a Java statement or not?标签是否是 Java 语句?
【发布时间】:2018-09-24 16:54:33
【问题描述】:

标签是否是 Java 语句,如果标签是语句,则它在 Java 语言规范中定义为语句吗?

我的问题与我发送给 Oracle 的错误报告中 Jan Lahoda 的以下回复有关。我无法在那里讨论它,因为我无法在 OpenJDK Jira 中获得帐户。

https://bugs.openjdk.java.net/browse/JDK-8211052

例如: A: B: while (true) continue A; 应用“continue”的语句不是“while (true) continue A;”,而是“B: while (true) continue A;”,规范要求 continue 的目标是 while/do/for 语句,这里没有实现.因此出现编译时错误。

我认为 Java 中的标签不是语句,在 Jan 的示例中,AB 标签都与同一个 while 循环语句相关,因此不应触发编译时错误。

加法:

Java 中的 labeled while/do/for 语句不是 while/do/for 语句吗?

【问题讨论】:

  • @Thomas 这是一个理论用例。 Java 允许一个循环有多个标签,但 continuebrake 语句在处理这些多个标签时存在不一致。
  • 重读specification:它将“LabeledStatement”定义为“label: statement”,其中“statement”可以是“LabeledStatement”,因此“labelA: labelB: statment”应该 被允许(尽管它没有多大意义,我可能会错过一些东西)。只是为了完整:标签本身不是语句,但可以是语句的一部分。

标签: java jls


【解决方案1】:

按照JLS一个Statement即可

StatementWithoutTrailingSubstatement
LabeledStatement
IfThenStatement
IfThenElseStatement
WhileStatement
ForStatement

LabeledStatement 存在

Identifier : Statement

并声明

标识符被声明为立即包含的语句的标签

所以如果出现像这样的循环

public void method() {
    loop1: loop2: while (true) {
        if (true) {
            break loop1;
        } else {
            continue loop1;
        }
    }
}

Label 中的 Statement loop1 是整个 loop2 ... 的东西。

如果我们查看break 的定义,则表明

break 目标不必是 switch、while、do 或 for 语句。

而对于 continue 它声明

continue 目标必须是 while、do 或 for 语句,否则会发生编译时错误。

这些定义正确地符合编译器的要求, 或 for 语句”.


关于您的实际问题:标签是否是 Java 语句?

以下代码完全合法,编译良好​​p>

public void method() {
    loop:;
}

这遵循Statement -> LabeledStatement -> Identifier 的扩展:Statement -> 循环:Statement -> 循环:StatementWithoutTrailingSubstatement -> 循环:EmptyStatement ->

loop : ;

不,标签本身不是语句,而是一个标识符(然后称为“标签”)加上一个colom加上一个EmptyStatement;)。


Java 中的while/do/for 语句不是标注为while/do/for 语句吗?

不!
LabeledStatement 就是这样:LabeledStatement。标记为 Statement -> Label -> Identifier : Statement -> Identifier : WhileStatement 的 while 与 Statement -> WhileStatement 根本不同!

【讨论】:

  • 我重复我的附加问题。 Java中的labeled while/do/for语句不是while/do/for语句吗?
  • @RostislavKrasny 不,为什么会这样?带标签的语句是带标签的语句,带标签的循环是带标签的循环。
  • @RostislavKrasny 不,带标签的 while/do/for 语句不是 while/do/for 语句。
  • @RostislavKrasny 在语言规范/语法术语中:是的,“命名的猫”不是“猫”,而是“命名的”。
  • @RostislavKrasny 你需要弄清楚你使用了什么词,你称之为“标签”的字母的确切顺序是什么?在l: if(...) { ... } 中,整个事物都是一个语句,在这种情况下,它甚至是一个带有if ... 部分是嵌套语句的LabeledStatement,l 是一个标记if 语句的标识符。您的最后一个问题没有意义,因为break 没有“使用”“标记语句”the expansion rule is break Identifier(opt)
【解决方案2】:

JLS, Section 14.16,谈continue声明:

continue 目标必须是whiledofor 语句,否则会出现编译时错误。

很简单,但让我们看一下带标签语句的语法 (Section 14.7)。

标签声明:

    标识符:声明

它通常可以包含另一个语句,依次可能是whiledofor(“wdf”)语句,或另一个带标签的语句(第 14.5 节)(或其他类型的语句)。

但是标签本身并不是一个陈述;它需要另一个语句作为自身的一部分。

接下来,嵌套的标签语句是允许的,所以通常你可以这样做:

A: B: yourStatementHere;

如果需要,您可以进一步嵌套:

A: B: C: D: E: F: G: yourStatementHere;

然而,与

A: B: while (true) continue A;

A: 标记的语句是另一个 标记语句,而不是“wdf”语句,即使B: 标记语句本身包含while声明。

如果您戴上律师的帽子,您可以争辩说,上面关于 continue 语句需要引用“wdf”语句的句子并没有说明“wdf”语句嵌套在带标签的语句中,所以它应该是编译器错误。

这对我来说似乎很挑剔;或许 JLS 应该有一个子句表明“wdf”语句本身可以嵌套在带标签的语句中。

但在此之前,这似乎是 JLS 提供的措辞的正确结果(如果不是有意的话),如上所述。

那么为什么break 允许这样做呢?

A: B: while (true) break A;  // no error

在 JLS 的第 14.15 节中没有相应的行,它讨论了 break 语句,强制 break 语句的目标必须是“wdf”语句。 break 语句仍必须在“wdf”语句(或switch 语句)内,但没有相应要求其标签引用特定类型的语句。

【讨论】:

  • 你如何得出一个结论,标记为 while/do/for 语句不是 while/do/for 语句? JLS在哪里定义它?为什么brake 没有问题?
  • 我添加了对break 的解释。此外,显然标记语句内的“wdf”语句仍然只是标记语句。没有规定“wdf”语句位于带标签的语句中。如果它需要引用我,那么它不能引用我的房子,即使我在我的房子里。
猜你喜欢
  • 2016-11-17
  • 2013-07-21
  • 1970-01-01
  • 2018-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-05
相关资源
最近更新 更多