【发布时间】:2022-12-09 12:50:02
【问题描述】:
让我们考虑一些关于 Java 中的标签和中断语句的示例,并尝试通过 OpenJDK (v18) javac 对其进行编译。主要目标是获得标签和分支(并继续)的准确语义。
版本 1。
public class L {
public static void main( String[] args) {
System.out.println( "Start\n");
Label1:
Label2:
break Label1;
//break Label2;
System.out.println( "Finish\n");
}
}
编译和反汇编。
$ javac L.java && echo $?
0
$ javap -c L
...
Code:
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #13 // String Start\n
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
11: ldc #21 // String Finish\n
13: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: return
}
字节码中没有任何 goto 指令。 (可能是字节码生成过程中优化的结果。这个例子的 AST 有一个 JCLabeledStatement 和一个 JCBreak 树节点。)以两种方式改变例子。
版本 2。
//break Label1;
break Label2;
它仍然像 Version1。
版本 3。
break Label1;
break Label2;
...
$ javac L.java
L.java:8: error: undefined label: Label2
break Label2;
^
1 error
Version3 不正确吗? javac 编译 Version1 和 Version2 的时候是 feature 吗?或者示例都不正确,但 OpenJDK 的 javac 不会根据 JAVA 语言标准捕获语法错误。
可能的解释。
Label1:
Label2:
break Label1;
方法
Label1: {
Label2: {
break Label1;
}
}
和 Version3 意味着
Label1: {
Label2: {
break Label1;
}
}
break Label2;
当然 break Label2 尝试在其范围之外使用 Label2。
(许多关于 break 的教程都集中在 for/while 上。)
【问题讨论】:
-
你读过the language spec了吗?
-
感谢您的链接。现在看来我明白了我最初在语法含义上的错误。
标签: java