Unreachable Statements in Java – Java 中的无法访问语句

最后修改: 2023年 11月 11日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll talk about the Java specification that states that the compiler should raise an error if any statement is unreachable. An unreachable statement is a code that can never be executed during the program execution because there is no way for the program flow to reach it. We’ll see various code examples that correspond to this definition.

在本教程中,我们将讨论 Java 规范,该规范规定,如果任何语句无法访问,编译器应引发错误。无法到达的语句是指在程序执行过程中永远无法执行的代码,因为程序流无法到达该语句。我们将看到与此定义相对应的各种代码示例。

2. Code After break Instruction in a Loop

2.循环中 break 指令之后的代码

In a loop, if we put instructions after a break statement, they’re not reachable:

在循环中,如果我们将指令放在 break 语句之后,它们将无法到达:

public class UnreachableStatement {
    
    public static void main(String[] args) {
        for (int i=0; i<10; i++) {
            break;
            int j = 0;
        }
    }

}

Let’s try to compile our code with javac:

让我们尝试使用 javac 来编译我们的代码:

$ javac UnreachableStatement.java
UnreachableStatement.java:9: error: unreachable statement
            int j = 0;
                ^
1 error

As expected, the compilation failed because the int j = 0; statement isn’t reachable. Similarly, an instruction after the continue keyword in a loop isn’t reachable:

不出所料,编译失败的原因是无法访问 int j = 0; 语句。同样,循环中 continue 关键字后的指令也无法执行:

public static void main(String[] args) {
    int i = 0;
    while (i<5) {
        i++;
        continue;
        int j = 0;
    }
}

3. Code After a while(true)

3.while(true) 之后的代码

A while(true) instruction means the code within runs forever. Thus, any code after that isn’t reachable:

while(true) 指令意味着其中的代码将永远运行。 因此,之后的任何代码都无法执行:

public static void main(String[] args) {
    while (true) {}
    int j = 0;
}

Once again, the statement int j = 0; isn’t reachable in the previous code. This remark is also valid for the equivalent code using the do-while structure:

同样,在前面的代码中,语句 int j = 0; 是无法执行的。此注释同样适用于使用 dowhile 结构的等价代码:

public static void main(String[] args) {
    do {} while (true);
    int j = 0;
}

On the other hand, any code inside a while(false) loop isn’t reachable:

另一方面,while(false) 循环中的任何代码都是不可访问的:

public static void main(String[] args) {
    while (false) {
        int j = 0;
    }
}

4. Code After Method Returns

4.方法返回后的代码

A method immediately exits on a return statement. Hence, any code after this instruction isn’t reachable:

方法会在 return 语句中立即退出。因此,该指令之后的任何代码都无法执行:

public static void main(String[] args) {
    return;
    int i = 0;
}

Once more, the int j = 0; line isn’t reachable, provoking a compiler error. Similarly, when a throw statement isn’t enclosed within a try-catch block or specified in the throws clause, the method completes exceptionally. Thus, any code after this line isn’t reachable:

再一次,int j = 0;行无法到达,导致编译器出错。同样,当 throw 语句未包含在 try-catch中或未在 throws 子句中指定时,方法会异常完成。因此,此行之后的任何代码都无法执行:

public static void main(String[] args) throws Exception {
    throw new Exception();
    int i = 0;
}

To recap, if all code branches return, the following code isn’t reachable by any means:

概括地说,如果所有代码分支都返回,那么下面的代码无论如何都无法到达:

public static void main(String[] args) throws Exception {
    int i = new Random().nextInt(0, 10);
    if (i > 5) {
        return;
    } else {
        throw new Exception();
    }
    int j = 0;
}

In this code, we chose a random number between 0 (inclusive) and 10 (exclusive). If this number is greater than 5, we return immediately, and if not, we throw a generic Exception. Thus, there is no possible execution path for the code after the if-else block.

在这段代码中,我们选择了一个介于 0(包含)和 10(不包含)之间的随机数。如果该数字大于 5,我们将立即返回;如果该数字小于 5,我们将抛出一个通用的 异常。因此,if-else 块之后的代码没有可能的执行路径。

5. Dead but Reachable Code

5.死亡但可触及的代码

Lastly, let’s notice that even obvious dead code isn’t mandatorily unreachable from the compiler’s perspective. In particular, it doesn’t evaluate the conditions inside an if statement:

最后,让我们注意到即使是明显的死代码,从编译器的角度来看也并非强制不可访问。特别是,它不会评估 if 语句中的条件:

public static void main(String[] args) {
    if (false) {
        return;
    }
}

This code compiles successfully even if we know at first glance that the code inside the if block is dead code.

即使我们一看就知道 if 块内的代码是死代码,这段代码也能成功编译。

6. Conclusion

6.结论

In this article, we looked at many unreachable statements. There is an argument in the developer community about whether unreachable code should raise a warning or an error. The Java language follows the principle that every written code should have a purpose, thus raising an error. In other languages like C++, as the compiler can execute the code in spite of its incoherencies, it only raises a warning.

在本文中,我们研究了许多不可达语句。在开发人员社区中,对于不可达代码应该引发警告还是错误存在争议。Java 语言遵循的原则是,每一段编写的代码都应该有其目的,因此会引发错误。而在其他语言(如 C++)中,由于编译器可以执行不连贯的代码,因此只会发出警告。