Lio*_*ion 82 java halting-problem
while
在Java中查看以下无限循环.它会导致它下面的语句出现编译时错误.
while(true) {
System.out.println("inside while");
}
System.out.println("while terminated"); //Unreachable statement - compiler-error.
Run Code Online (Sandbox Code Playgroud)
以下相同的无限while
循环,但工作正常,并不会发出任何错误,我只是用布尔变量替换条件.
boolean b=true;
while(b) {
System.out.println("inside while");
}
System.out.println("while terminated"); //No error here.
Run Code Online (Sandbox Code Playgroud)
在第二种情况下,循环后的语句显然无法访问,因为布尔变量b
为true,编译器根本不会抱怨.为什么?
编辑:下面的版本while
陷入了无限循环,但是对于它下面的语句没有发出编译器错误,即使if
循环中的条件总是false
因此,循环也永远不会返回并且可以由编译器在编译时本身.
while(true) {
if(false) {
break;
}
System.out.println("inside while");
}
System.out.println("while terminated"); //No error here.
Run Code Online (Sandbox Code Playgroud)
while(true) {
if(false) { //if true then also
return; //Replacing return with break fixes the following error.
}
System.out.println("inside while");
}
System.out.println("while terminated"); //Compiler-error - unreachable statement.
Run Code Online (Sandbox Code Playgroud)
while(true) {
if(true) {
System.out.println("inside if");
return;
}
System.out.println("inside while"); //No error here.
}
System.out.println("while terminated"); //Compiler-error - unreachable statement.
Run Code Online (Sandbox Code Playgroud)
编辑:与if
和相同的事情while
.
if(false) {
System.out.println("inside if"); //No error here.
}
Run Code Online (Sandbox Code Playgroud)
while(false) {
System.out.println("inside while");
// Compiler's complain - unreachable statement.
}
Run Code Online (Sandbox Code Playgroud)
while(true) {
if(true) {
System.out.println("inside if");
break;
}
System.out.println("inside while"); //No error here.
}
Run Code Online (Sandbox Code Playgroud)
以下版本while
也陷入了无限循环.
while(true) {
try {
System.out.println("inside while");
return; //Replacing return with break makes no difference here.
} finally {
continue;
}
}
Run Code Online (Sandbox Code Playgroud)
这是因为finally
即使return
语句在try
块本身内遇到它,也始终执行该块.
Way*_*ett 105
编译器可以轻松明确地证明第一个表达式总是导致无限循环,但对于第二个表达式来说并不容易.在你的玩具示例中它很简单,但如果:
编译器显然没有检查你的简单案例,因为它完全放弃了这条道路.为什么?因为规范禁止它更难.见14.21节:
(顺便说一句,我的编译器在声明变量时会抱怨final
.)
Kib*_*bee 55
根据规范,以下是关于while语句的说法.
如果至少满足下列条件之一,则while语句可以正常完成:
- while语句是可访问的,条件表达式不是值为true的常量表达式.
- 有一个可到达的break语句退出while语句.
因此,编译器只会说如果while条件是具有true值的常量,或者while内有break语句,则while语句后面的代码无法访问.在第二种情况下,由于b的值不是常数,因此不认为其后面的代码是不可达的.这个链接背后有更多的信息,可以为您提供有关什么是什么,什么不被认为无法到达的更多细节.
kba*_*kba 10
因为分析变量状态很难,所以编译器几乎只是放弃了,让你按照自己的意愿行事.此外,Java语言规范有关于如何允许编译器检测无法访问的代码的明确规则.
有许多方法可以欺骗编译器 - 另一个常见的例子是
public void test()
{
return;
System.out.println("Hello");
}
Run Code Online (Sandbox Code Playgroud)
这是行不通的,因为编译器会意识到该区域是不可行的.相反,你可以做到
public void test()
{
if (2 > 1) return;
System.out.println("Hello");
}
Run Code Online (Sandbox Code Playgroud)
这可以工作,因为编译器无法意识到表达式永远不会是假的.