2

可能重复:
为什么此代码给出“无法访问的语句”错误?

这似乎很简单的问题,我在一本书中找到了这个问题。如果有人帮我弄清楚为什么我会出错。

    do {
        System.out.print("inside do");
    } while (false);
    while (false) { // error
        System.out.print("inside while");
    }
    System.out.print("outside");

我想,据我说,输出应该在 dooutside 里面。但是,它显示Compiler Error : Unreachable Statement。然后,我试图弄清楚,为什么,它显示Compilation error : Unreachable Statement*。所以,我像这样更改上面的代码

  boolean i = false;  
  do {
        System.out.print("inside do");
    } while (false);
    while (i) { // ok
        System.out.print("inside while");
    }
    System.out.print("outside");

现在,它显示了预期的输出,即在 dooutside 内部。所以,我的问题是 - 第一种和第二种情况有什么区别?另外,当我检查

if(false){ 
  //something here
   }

然后,上面的代码执行没有任何错误。

4

2 回答 2

6

前两个示例之间的主要区别在于,在第一种情况下,条件是常数,而在第二种情况下则不是。

例如,如果您更改boolean i = false;final boolean i = false;,您将得到相同的编译错误,因为 i 现在是一个常量。

不可达语句的规则在JLS 14.21中定义。特别是对于if允许可能是常数的if(DEBUG)结构有一个特殊的处理。DEBUG

至于do / while,里面的语句会执行一次,所以没有问题。

有关此相关帖子中常量的更多详细信息。

于 2012-12-22T07:40:25.953 回答
5

编译器给你一个Unreachable statement错误,因为你的System.out.print("inside while");代码永远无法到达

while (false) { // error
    System.out.print("inside while");
}

编译器知道这while (false)永远不会是真的,并警告你(有错误)关于死代码。

相反,如果您将变量放入while,因为变量的性质是它们可以变化(更改),编译器的静态分析不会识别无法访问的代码。(即使在许多情况下,您或我可以看到它并说“该代码永远不会运行”;编译器的分析相当肤浅,这不是它的主要工作。您可以使用更强大的分析和代码覆盖工具采用。)

在这方面if (false),这是JLS 必须说的

例如,以下语句会导致编译时错误:

while (false) { x=3; }

因为声明x=3;无法到达;但表面上类似的情况:

if (false) { x=3; }

不会导致编译时错误。优化编译器可能会意识到该语句x=3;将永远不会被执行,并且可能会选择从生成的类文件中省略该语句的代码,但在x=3;此处指定的技术意义上,该语句不被视为“不可访问”。

这种不同处理的基本原理是允许程序员定义“标志变量”,例如:

static final boolean DEBUG = false;

然后编写代码,例如:

if (DEBUG) { x=3; }

这个想法是应该可以将值DEBUG从 false 更改为 true 或从 true 更改为 false,然后正确编译代码,而无需对程序文本进行其他更改。

于 2012-12-22T07:29:30.843 回答