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规范的某个地方,是否有这种行为可能有用的情况?

+0

难道你需要一个'返回0;'(或同等学历)后',而(真);',只是为了使编译器幸福吗?我知道我有Java抱怨方法不会返回正确的类型。这就是说,我完全可以看到这是一个编译程序。 – 2009-12-24 14:49:55

+0

非常有趣...我很惊讶它实际编译。 – cjstehno 2009-12-24 14:52:12

我只是引用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?!"); } 
} 
+0

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);不会被编译器视为无法访问,否则会引发编译时错误!

+2

你的答案有误导性。计算机程序不可能识别任意程序是否停止,但检查“特定程序”是否停止绝对不是不可能的。当然,'while(true);'没有'break'或'goto'语句是一个无限循环的事实可以由编译器检查。 – 2009-12-24 15:00:30

+0

是的,我纠正了上述情况。 – Alex 2009-12-24 15:00:53

+0

boolean test = true; (测试) 不一定是无限循环。另一个线程可能会改变'test'的值。 – 2009-12-25 18:58:12

是的,您可以在某些线程中看到这些“无限”循环,例如在某个端口上侦听传入消息的服务器线程。

重读这个问题之后....

Java理解while(true);永远不能完成,它不完全追踪下面的代码。

boolean moo = true; 
while (moo); 

此信息是否有用?疑。

+0

那究竟是“在做什么”? – 2009-12-24 15:05:50

+0

这不一定是无限循环。另一个线程可能会将'moo'设置为false。 – 2009-12-25 18:59:34

Java规范定义了一个名为Unreachable statements的概念。您的代码中不允许有无法访问的语句(这是编译时错误)。根据定义,while(true);语句使以下语句无法访问。在Java中的while(true);语句之后,您甚至不允许使用return语句。请注意,尽管在通用情况下Halting problem是不可判定的,但“不可访问的声明”的定义比仅仅停止更为严格。它正在决定非常具体的案例程序肯定不会停止。编译器理论上无法检测到无限循环和无法访问的语句,但它必须检测规范中定义的特定情况。

+0

但它编译。另外:while(true){// code}也编译,而不返回int! – Alex 2009-12-24 15:41:15

+3

'while(true)'is not unreachable(显然!)。 'while(true)'后面的任何语句都无法访问。 – 2009-12-24 21:05:26

+0

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操作内存空间。