无法访问的代码编译没有错误 - 如何?

2022-08-31 17:13:05

根据我的理解,下面的代码不应该编译,因为语句“我无法访问”在.return

但是,当我运行此代码时,它的编译绝对正确。

同样从JLS:无法访问的语句中,它不应该编译。

来自规范,在 14.21 无法访问语句:

如果同时满足以下两项条件,则 try 语句可以正常完成:

  • try 块可以正常完成,或者任何捕获块可以正常完成。

  • 如果 try 语句有一个 finally 块,则 finally 块可以正常完成。

在这里,try块不能正常完成,但捕获块可以和最终块一样完成,所以我在这里感到困惑

    public class Test1 {
     public static void main(String[] args) {
        try {
            return;

        } catch (Exception e) {
            System.out.println("catch");

        } finally {
            System.out.println("finally");
        }
        System.out.println("I am unreachable??!!!");
    }
}

有人可以帮助我理解这种行为吗?


答案 1

我相信这些是JLS 14.21的相关引用:

  • 不是开关块的空块可以在可访问的情况下正常完成。

    不是开关块的非空块可以正常完成,而其中的最后一个语句可以正常完成。

    非空块中不是开关块的第一个语句在可访问块的情况下是可访问的。

    非开关块的非空块中的所有其他语句 S 都可以访问,因为 S 前面的语句可以正常完成

所以你的

System.out.println("I am unreachable??!!!");

语句是可访问的 iff(这意味着“当且仅当”),try 语句可以正常完成,这会导致下一个引号:

  • 如果以下两项都为真,则 try 语句可以正常完成:

    • try 块可以正常完成,或者任何捕获块可以正常完成

    • 如果 try 语句有一个 finally 块,则 finally 块可以正常完成

由于您的块可以正常完成,并且您有一个可以正常完成的块,因此语句可以正常完成。因此,无论块内的语句如何,它后面的语句都被视为可访问的。catchfinallytrySystem.out.println("I am unreachable??!!!");return;try

注意or

try 块可以正常完成,或者任何捕获块可以正常完成。

这需要块至少一个块正常完成。它不需要块和块都正常完成。trycatchtrycatch

最后,此行为背后的逻辑:

编译器不应该分析 try 块是否可以抛出 .原因是类层次结构包括已检查和未检查的异常,并且未选中的异常不在子句中声明(如果用某些已检查的异常替换,例如,编译器会抱怨您的 try 块永远不会引发该异常,这将使该块无法访问)。ExceptionExceptionthrowsExceptionIOExceptioncatch

因此,由于您有一个可以正常完成的块,编译器假定此 catch 块可以访问,因此整个 try 语句可以正常完成,即使该块无法正常完成。catch (Exception e)try

最后的块(如果存在)也必须能够正常完成,因为块也会被执行,因此如果它不能正常完成,整个try语句就无法正常完成。finally


答案 2

你已经尝试回来了。

如果有异常,它直接去捕获怎么办。因此,就编译器而言,它并非无法访问,并且正在成功编译。

编译将失败,如果你也将返回捕获

此外,根据 JLS 14.21

如果中断目标中没有 try 语句,其 try 块包含中断语句,或者存在 try 语句的 try 块包含中断语句,并且这些 try 语句的所有 finally 子句都可以正常完成,则可访问的中断语句将退出该语句。

当您在尝试和捕获中都有返回时,请参阅下面的输出:

jshell>  public class Test1 {
   ...>     public static void main(String[] args) {
   ...>         try {
   ...>             return;
   ...>
   ...>         } catch (Exception e) {
   ...>             return;
   ...>
   ...>         }
   ...>
   ...>         System.out.println("I am unreachable??!!!");
   ...>     }
   ...> }
|  Error:
|  unreachable statement
|          System.out.println("I am unreachable??!!!");
|          ^------------------------------------------^

当您在 finally 语句中返回并且编译将失败时,情况也是如此。

在以下情况下,声明帖子尝试将被视为可访问:

1) Try has a return statement with catch and finally not having return statement
2) Try does not have a return statement with catch having or not having return statement and finally not having return statement
3) Try, catch and finally not having return statement

推荐