如果我尝试编译
for(;;) { } System.out.println("End");
Java编译器产生错误说Unreachable statement
.但是,如果我添加另一个" 无法访问 "(根据我)break
声明并使其成为:
for(;;) { if(false) break; } System.out.println("End");
它汇编.为什么它不会产生错误?
该行为在无法访问的语句的JLS描述中定义:
如果if-then语句可以访问,则可以访问then语句.
因此break;
,无论条件如何,编译器都会确定then-statement()是可以访问的if
.
更进一步,强调我的:
for
如果至少满足下列条件之一,则基本语句可以正常完成:
for语句是可到达的,有一个条件表达式,条件表达式不是值为true的常量表达式(第15.28节).
有一个可到达的
break
语句退出for语句.
所以for可以正常完成,因为then语句包含a break
.正如您所注意到的,如果您替换break
为它将无法工作return
.
理由在本节末尾解释.实质上,if
有一个特殊的处理,以允许如下构造:
if(DEBUG) { ... }
其中DEBUG可能是编译时常量.
正如我对类似问题的回答所解释的那样,特定结构if(compile-time-false)
作为明确的后门免于不可达规则.在这种情况下,编译器会将您break
视为可达.
来自JLS
如果至少满足下列条件之一,则if-then语句可以正常完成:
> if-then语句是可访问的,条件表达式不是值为true的常量表达式.
> then语句可以正常完成.
所以if(false)
是允许的.
这种"有条件地编译"的能力对二进制兼容性有重大影响和关系.如果编译了一组使用这种"flag"变量的类并且省略了条件代码,则稍后仅仅分发包含该标志定义的类或接口的新版本是不够的.因此,对标志值的更改与预先存在的二进制文件不是二进制兼容的.(还有其他原因导致这种不兼容性,例如在switch语句中使用case标签中的常量;)