为了账号安全,请及时绑定邮箱和手机立即绑定

无法无误地编译无法访问的代码 - 如何?

无法无误地编译无法访问的代码 - 如何?

叮当猫咪 2021-06-04 18:45:11
根据我的理解,以下代码不应编译,因为“我无法访问”语句在return.但是,当我运行这段代码时,它编译得非常好。同样来自 JLS: Unreachable Statements它不应该编译。来自规范,在 14.21 Unreachable Statements:如果以下两项都为真,try 语句可以正常完成:try 块可以正常完成,或者任何 catch 块都可以正常完成。如果 try 语句有一个 finally 块,那么 finally 块可以正常完成。这里的try块不能正常完成,但是catch块和finally块一样可以,所以我在这里很困惑    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??!!!");    }}有人可以帮助我理解这种行为吗?
查看完整描述

3 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

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

  • 一个不是 switch 块的空块可以正常完成,如果它是可到达的。

    不是 switch 块的非空块可以正常完成,如果其中的最后一条语句可以正常完成。

    不是 switch 块的非空块中的第一个语句是可到达的,如果该块是可到达的。

    非空块(不是 switch 块)中的每个其他语句 S 都是可达的,如果 S 之前的语句可以正常完成

所以你的

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

语句是可达 iff(即“当且仅当”)try 语句可以正常完成,这导致下一个引用:

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

    • try 块可以正常完成,或者任何 catch 块都可以正常完成

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

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

注意or

try 块可以正常完成,或者任何 catch 块都可以正常完成。

这需要try至少其中一个catch块才能正常完成。它不需要try块和catch块都正常完成。

最后,这种行为背后的逻辑:

编译器不应该分析 try 块是否可以抛出Exception. 原因是Exception类层次结构包括受检异常和非受检异常,并且未受检异常没有在throws子句中声明(如果您替换Exception为某些受检异常,例如IOException,编译器会抱怨您的 try 块永远不会抛出该异常,这将使该catch块不可达)。

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

finally块,如果存在,也必须能够正常完成,因为该finally块也被执行了,所以如果不能正常完成,整个try语句也不能正常完成。



查看完整回答
反对 回复 2021-06-10
?
守着一只汪

TA贡献1872条经验 获得超3个赞

你有回报。


如果有异常直接去捕获怎么办。因此,它在编译器方面并非不可访问,并且正在成功编译。


如果您也将在 catch 中返回,则编译将失败


此外,根据JLS 14.21:


如果在 break 目标中没有 try 语句的 try 块包含 break 语句,或者有 try 语句的 try 块包含 break 语句并且这些 try 语句的所有 finally 子句可以完成,则可达 break 语句将退出语句一般。


当您在 try 和 catch 中都返回时,请参阅下面的输出:


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 语句中返回并且编译将失败时,情况也会类似。


在以下情况下,语句 post try 将被视为可达:


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


查看完整回答
反对 回复 2021-06-10
?
jeck猫

TA贡献1909条经验 获得超7个赞

试图给出一个更简单的问题原因,代码是可访问的,以防在 try 块中发生异常。在这种情况下,控制会进一步转到 catch 块,然后是 finally 块。在 finally 块之后,将执行特定的语句。


try {

            return;                                 //line 1


        } catch (Exception e) {

            System.out.println("catch");            //line 2


        } finally {

            System.out.println("finally");          //line 3

        }

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

这意味着,有 2 种情况,因此有 2 个流:


第 1 行 -> 第 3 行 -> 返回(如果没有例外)

第 1 行(发生异常) -> 第 2 行 -> 第 3 行 -> 第 4 行(以防 try 出现异常)

只有当我们不留下任何控制权到达那里的可能性时,这条线才会变得不可到达。有两种方法:


从 catch 块返回

从 finally 块返回。

在这两种情况下,控制权永远不会流向那条线。


try {

            return;                                 //line 1


        } catch (Exception e) {

            System.out.println("catch");            //line 2

            return;                                 //return control

        } finally {

            System.out.println("finally");          //line 3

            return;                                 //or return from here

        }

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

我希望现在它可以清楚地说明问题的实际原因。


查看完整回答
反对 回复 2021-06-10
  • 3 回答
  • 0 关注
  • 164 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信