而(真);循环在不处于 void 中时引发无法访问的代码

我当时在Java中做一些小程序。我知道如果我写while(true);程序将冻结在这个循环中。如果代码是这样的:

测试 1:

public class While {
    public static void main(String[] args) {
        System.out.println("start");
        while (true);
        System.out.println("end");
    }
}

编译器向我抛出错误:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Unreachable code
    at While.main(While.java:6)

我不知道这个错误存在。但是我明白为什么它被扔了。当然,第 6 行无法访问,从而导致编译问题。然后我测试了这个:

测试 2:

public class While {
    public static void main(String[] args) {
        System.out.println("start");
        a();
        b();
    }
    static void a() {
        while(true);
    }
    static void b() {
        System.out.println("end");
    }
}

由于某种原因,程序正常运行(控制台打印“开始”,然后冻结)。编译器无法检查 void a() 的内部,并看到它不可访问。为了确定我试过了:

测试 3:

public class While {
    public static void main(String[] args) {
        System.out.println("start");
        a();
        System.out.println("end");
    }
    static void a() {
        while(true);
    }
}

结果与测试 2 相同。

经过一些研究,我发现了这个问题因此,如果括号内的代码是变量,编译器不会引发异常。这是有道理的,但我不认为这同样适用于空洞

问:那么,如果 void b() (Test 2) 和 System.out.println(“end”); (Test 3) 无法访问,为什么编译器会在 Test 1 中向我抛出错误呢?

编辑:我在C++中尝试了测试1:

#include <iostream>

using namespace std;

int main()
{
    cout << "start" << endl;
    while(true);
    cout << "end" << endl;
    return 0;
}

编译器没有抛出任何错误,然后我得到了与测试2和测试3相同的结果。所以我想这是一个java的东西?


答案 1

语言规范有一个确切的定义,编译器应该将什么视为无法访问的代码,另请参阅 https://stackoverflow.com/a/20922409/14955

特别是,它不关心一个方法是否完成,并且不查看其他方法的内部。

它不会做得更多。

但是,您可以获得像FindBugs这样的静态代码分析工具来获得“更深入”的分析(但是,不确定它们是否检测到您描述的模式,并且,正如其他人所指出的那样,无论如何,所有通用的停止问题都无法在算法上解决,因此必须对“尽力而为”进行合理的定义”


答案 2

一般来说,不可能绝对肯定地确定某物是否可到达。

为什么?它相当于停止问题

停止问题问道:

给定任意计算机程序的描述,确定程序是完成运行还是继续永远运行。

这个问题已被证明是无法解决的。


X 段代码是否可访问,与说明代码之前是否停止是一样的。

因为这是一个无法解决的问题,编译器(在Java或任何其他语言中)不会非常努力地解决它。如果它碰巧确定它确实无法访问,那么您将收到警告。如果没有,它可能或可能无法到达。

在 Java 中,无法访问的代码是编译器错误。因此,为了保持兼容性,语言规范准确地定义了编译器应该尝试的“难度”。(根据其他答案,这是“不要进入另一个函数”。

在其他语言(如C++)中,编译器可能会进一步进行优化。(在内联函数并发现它永远不会返回后,可能会检测到无法访问的代码。


推荐