如果我尝试编译
for(;;)
{
}
System.out.println("End");
Run Code Online (Sandbox Code Playgroud)
Java编译器产生错误说Unreachable statement.但是,如果我添加另一个" 无法访问 "(根据我)break声明并使其成为:
for(;;)
{
if(false) break;
}
System.out.println("End");
Run Code Online (Sandbox Code Playgroud)
它汇编.为什么它不会产生错误?
为什么这段代码没有给出"无法访问的代码"错误?由于布尔值只能为true或false.
public static void main(String args[]) {
boolean a = false;
if (a == true) {
} else if (a == false) {
} else {
int c = 0;
c = c + 1;
}
}
Run Code Online (Sandbox Code Playgroud) 以下代码给出了unreachable statement编译器错误
public static void main(String[] args) {
return;
System.out.println("unreachable");
}
Run Code Online (Sandbox Code Playgroud)
有时为了测试目的,希望阻止调用方法,因此快速执行此操作(而不是在使用它的任何地方对其进行注释)是立即从方法返回,以便该方法不执行任何操作.然后我总是这样做以解决编译器错误
public static void main(String[] args) {
if (true) {
return;
}
System.out.println("unreachable");
}
Run Code Online (Sandbox Code Playgroud)
我只是好奇,为什么它是一个编译错误?它会以某种方式打破Java字节码,它是为了保护程序员还是其他东西?
另外(这对我来说更有趣),如果编译java到字节码进行任何类型的优化(或者即使它没有)那么为什么它不会在第二个例子中检测到明显无法访问的代码呢?编译器伪代码用于检查语句是否无法访问?
我该如何理解这个Java编译器的行为?
while (true) return;
System.out.println("I love Java");
// Err: unreachable statement
if (true) return;
System.out.println("I hate Java");
// OK.
Run Code Online (Sandbox Code Playgroud)
谢谢.
编辑:
几分钟后我发现了这一点:
在第一种情况下,编译器因无限循环而抛出错误.在这两种情况下,编译器都不会考虑语句内部的代码.
编辑二:
让我对javac印象深刻的是:
if (true) return; // Correct
}
while (true) return; // Correct
}
Run Code Online (Sandbox Code Playgroud)
看起来javac知道两个循环内部是什么,如果结果,但是当你编写另一个命令时(如第一个例子中),你得到非等效行为(看起来像javac忘记了循环内部/ if).
公共静态最终EDIT III:
作为此答案我可以此话(希望正确)的结果:作为表达if (arg) { ...; return;}和while (arg) { ...; return;}对Java是等效的两个语义和语法(在字节码)当且仅当argv是不恒定的(或有效最终型)的表达.如果argv是常量表达式字节码(和行为)可能不同.
免责声明
这个问题不是关于无法访问的语句,而是对逻辑等效表达式的不同处理,例如while true return和if true return.
研究方法如下:
static private void foo() {
try {
throw new FileNotFoundException();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
尽管最后一个catch块实际上无法访问,但此代码编译良好.
现在让评论 throw new FileNotFoundException();行
执行:
哎呀!我们看
Unreachable catch block for FileNotFoundException. This exception is never thrown from the try statement body
Run Code Online (Sandbox Code Playgroud)
奇怪.为什么java在这些情境中使用双重标准?
static private void foo(FileNotFoundException f) {
try {
throw f;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
工作以及构造函数调用
我注意到在不同版本的java编译器上,我看到编译此代码的不同结果.
public class …Run Code Online (Sandbox Code Playgroud) 几天前,我在与Java同事讨论这段代码:
for( ; ; ) { }
Run Code Online (Sandbox Code Playgroud)
这里没什么特别的,只是一个无限循环.
但我们想知道为什么这在语法上是正确的.如果您看一下JLS§14.14.1,您会看到:
for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement
Run Code Online (Sandbox Code Playgroud)
我理解ForInit并且ForUpdate可以省略.但至少我希望这Expression是强制性的,比如while循环:
while() {} // compile error, Expression is missed
Run Code Online (Sandbox Code Playgroud)
那么为什么可以在for循环中省略Expression呢?甚至一个人想得更多 - 为什么错过表达式解决了true?我的期望是将空表达式解析为false.
同样的想法对其他语言也有效(我用C和JavaScript尝试它,但我相信每个带有for循环的语言都是这样的).
为什么在for循环中(但在while循环中)Expression子句不是必需的?为什么空表达式解析true而不是false?
如果我有类似的代码
public static void main(String args[]){
int x = 0;
while (false) { x=3; } //will not compile
}
Run Code Online (Sandbox Code Playgroud)
编译器将投诉x=3无法访问的代码,但如果我有类似的代码
public static void main(String args[]){
int x = 0;
if (false) { x=3; }
for( int i = 0; i< 0; i++) x = 3;
}
Run Code Online (Sandbox Code Playgroud)
然后它通过内部代码正确编译if statement,for loop无法访问.为什么java工作流逻辑没有检测到这种冗余?任何用例?