Java是否识别无限循环?
考虑下面的代码示例:Java是否识别无限循环?
public class WeirdStuff {
public static int doSomething() {
while(true);
}
public static void main(String[] args) {
doSomething();
}
}
这是一个有效的Java程序,尽管该方法DoSomething的()应该返回一个int,但从来不会。如果你运行它,它会以无限循环结束。如果你把while循环的参数放在一个单独的变量中(例如boolean bool = true),编译器会告诉你在这个方法中返回一个int。
所以我的问题是:这是在Java规范的某个地方,是否有这种行为可能有用的情况?
我只是引用Java Language Specification,因为它是对这个相当清楚的:
这部分是专门用于单词的精确的解释“可达”。这个想法是,从构造函数,方法,实例初始化程序或包含语句的静态初始化程序的开头,到语句本身必须有一些可能的执行路径。分析考虑到了陈述的结构。除了特殊处理while,do和for语句的条件表达式的常量值为真以外,表达式的值在流分析中未被考虑。
...
while语句可以完成正常且仅当以下至少有一个为真:
- while语句是可到达的条件表达式不是一个常数表达与真值。
- 有一个可到达的break语句退出while语句。
...
在非空块每隔的statement不是一个开关块是当且仅当到达前S中的语句可以正常完成。
,然后应用上面的定义,以this:
如果一个方法被声明为返回类型,然后在其身体的每一个return语句(§14.17)必须有一个表达。如果方法的正文可以正常完成(§14.1),则会发生编译时错误。
换句话说,具有返回类型的方法必须通过使用一个返回语句,提供了一个值返回只返回;它不允许“落下其身体的末端”。
注意,这是可能的方法有一个声明的返回类型,但不包含return语句。这里有一个例子:
class DizzyDean { int pitch() { throw new RuntimeException("90 mph?!"); } }
JLS来救援! \ O / – Bombe 2009-12-24 21:50:41
如果您问是否可以使用无限循环,答案是肯定的。有很多情况下你想要永远运行的东西,尽管循环通常会在某个时候终止。
至于你的问题:“Java可以识别循环将无限?”答案是,计算机不可能有算法来确定程序是否会永久运行。阅读关于:Halting Problem
读了一会儿,你的问题也在问为什么doSomething()函数不会抱怨它没有返回一个int。
有趣的是下面的代码不会编译。
public class test {
public static int doSomething() {
//while(true);
boolean test=true;
while(test){
}
}
public static void main(String[] args) {
doSomething();
}
}
这表明,我认为,作为停机问题的维基页面提示,它是不可能有作为一个算法,以确定是否所有的问题将终止,但这并不意味着有人不加简单情况下:
while(true);
java规范。我上面的例子稍微复杂一点,所以Java不能将它记为无限循环。真的,这是一个奇怪的边缘情况,但它只是为了编译。也许有人会尝试其他组合。
编辑:不是无法访问的代码的问题。
import java.util.*;
public class test {
public static int doSomething() {
//while(true);
while(true){
System.out.println("Hello");
}
}
public static void main(String[] args) {
doSomething();
}
}
上面的作品,所以while(true);不会被编译器视为无法访问,否则会引发编译时错误!
你的答案有误导性。计算机程序不可能识别任意程序是否停止,但检查“特定程序”是否停止绝对不是不可能的。当然,'while(true);'没有'break'或'goto'语句是一个无限循环的事实可以由编译器检查。 – 2009-12-24 15:00:30
是的,我纠正了上述情况。 – Alex 2009-12-24 15:00:53
boolean test = true; (测试) 不一定是无限循环。另一个线程可能会改变'test'的值。 – 2009-12-25 18:58:12
是的,您可以在某些线程中看到这些“无限”循环,例如在某个端口上侦听传入消息的服务器线程。
重读这个问题之后....
Java理解while(true);永远不能完成,它不完全追踪下面的代码。
boolean moo = true;
while (moo);
此信息是否有用?疑。
那究竟是“在做什么”? – 2009-12-24 15:05:50
这不一定是无限循环。另一个线程可能会将'moo'设置为false。 – 2009-12-25 18:59:34
Java规范定义了一个名为Unreachable statements的概念。您的代码中不允许有无法访问的语句(这是编译时错误)。根据定义,while(true);
语句使以下语句无法访问。在Java中的while(true);
语句之后,您甚至不允许使用return
语句。请注意,尽管在通用情况下Halting problem是不可判定的,但“不可访问的声明”的定义比仅仅停止更为严格。它正在决定非常具体的案例程序肯定不会停止。编译器理论上无法检测到无限循环和无法访问的语句,但它必须检测规范中定义的特定情况。
但它编译。另外:while(true){// code}也编译,而不返回int! – Alex 2009-12-24 15:41:15
'while(true)'is not unreachable(显然!)。 'while(true)'后面的任何语句都无法访问。 – 2009-12-24 21:05:26
Pavel:对。当然,这就是我的意思。 – 2009-12-24 21:10:13
所以我的问题是:这是在某处Java规范
该方案是根据规范合法的Java。 JLS(和Java编译器)认识到该方法不能返回,因此不需要return
声明。事实上,如果在循环之后添加return
语句,那么Java编译器会给你一个编译错误,因为return语句是不可访问的代码。
并且有没有这种行为可能有用的情况?
我不这么认为,除非可能在模糊的单元测试中。
我偶尔会编写永远不会返回(通常)的方法,但是将当前线程置于不可中断的无限繁忙循环中很少有意义。
你可能会实现一个通用的接口,例如,尽管该方法可以用一个有意义的退出并返回值,您的特定的实现是一个有用的无限循环(例如,网络服务器),它从来没有的情况下它应该退出,即触发返回值的任何操作。
此外,关于像boolean x = true; while (x);
代码,这将编译上给出一个x
修改final
。我不知道如何,但我可以想象这是Java选择合理简单的常量表达式分析(这需要直截了当地定义,因为依赖于程序的这种拒绝,它是语言定义的一部分)。
关于无法陈述一些注意事项:
在java2 specs“不到的语句”的描述中可以找到。特别有趣下面的句子:
除特殊处理的而,做,并为语句,其条件表达式的常量值为true,表达式的值不考虑流程分析中的。
所以,显然无法从while (true);
退出无限循环。但是,还有两个选项:change cached values或直接入侵类文件或JVM操作内存空间。
难道你需要一个'返回0;'(或同等学历)后',而(真);',只是为了使编译器幸福吗?我知道我有Java抱怨方法不会返回正确的类型。这就是说,我完全可以看到这是一个编译程序。 – 2009-12-24 14:49:55
非常有趣...我很惊讶它实际编译。 – cjstehno 2009-12-24 14:52:12