【问题标题】:System.exit and finally code analysisSystem.exit 和 finally 代码分析
【发布时间】:2016-03-01 11:22:10
【问题描述】:

请帮我理解下面的代码,

案例 1:

finally{
    return;
    System.exit(1);
}

以上代码抛出编译时错误:

无法访问的代码

案例 2:

finally{
    System.exit(1);
    return;
}

上面的代码没有抛出任何编译/运行时错误,但是当我运行程序时就退出了。

我的问题是为什么设计人员认为在案例 1 中抛出编译时错误,而在案例 2 中他们没有。实际上,当您调用 System.exit(0) 时,程序将终止,这意味着它下面的代码无法访问。

【问题讨论】:

    标签: java


    【解决方案1】:

    return 是编译器知道的语言特性。 System.exit(1) 被编译器视为静态方法调用,类似于System.out.println(...)。编译器不知道调用这个方法实际上做了什么。

    【讨论】:

    • 正如“Ernest Kiwele”在下面的评论中提到的,上面的代码属于运行时和编译时的类别?
    【解决方案2】:

    在案例 1 中,您使用语言构造来退出块,之后的任何代码都将永远不会运行,因此会出现编译器错误。

    在案例 2 中,您正在调用一个强制 JVM 退出而不执行任何代码的方法,因此那里没有编译器错误。

    【讨论】:

      【解决方案3】:

      对于编译器,System.out.println() 和 System.exit() 之间没有区别 - 两者都只是方法。编译器不会分析它的内容。

      【讨论】:

        【解决方案4】:

        案例一:

          finally{
                return;
                System.exit(1);
            }
        

        这是无法访问的,因为编译器可以看到您正在从方法返回,因此不会运行更多代码。

        案例2:

        finally{
            System.exit(1);
            return;
        }
        

        上面的代码没有抛出任何编译/运行时错误,但是当我运行时 程序刚刚退出

        exit() 的文档回答这个问题:

        终止当前运行的 Java 虚拟机。论据 作为状态码;按照惯例,一个非零状态码 表示异常终止

        exit() 抛出的唯一异常是SecurityException

        【讨论】:

        • 你没有回答问题,用户问为什么System.exit(1)不被编译器视为return语句。
        【解决方案5】:

        编译器不检查方法的作用。编译器设计者做出的简单设计决定是 - return 语句之后的任何代码行(在同一块中)都是不可访问的

        无论您拨打System.exit() 还是explodeMyPC()(这实际上可能是您的PC 卡)都没有关系。

        【讨论】:

          【解决方案6】:

          这是运行时与编译时的区别。在第一种情况下,Java 编译器阻止了成功编译,因为语句System.exit(1) 永远无法执行(看它:如果执行了return 语句,那么就没有办法在同一个语句中执行任何其他语句方法。出于这个原因,Java 规范禁止了这种代码,并且编译器简单地禁止了这种代码。return 语言特性是编译器已知的,它强制期望没有进一步的代码。但是,System.exit(1) 是像任何其他 API 方法一样被视为方法调用。

          在第二种情况下,编译器不会像处理return; 语句那样处理System.exit(),这就是为什么语句的效果只留给运行时的原因。当这段代码在运行时执行时,System.exit(1); 行被命中,VM 退出,没有机会到达return 语句。但是,编译器认为这是完全合法的代码。

          【讨论】:

            【解决方案7】:

            在第一种情况下,您在调用 System.exit 之前从块中返回,这意味着 System.exit 永远无法到达。

            这是编译器可以识别的错误。

            编译器不知道 System.exit 的行为方式

            根据特定的库调用添加流分析会很慢而且很脆弱。

            这样的分析最好留给静态分析工具。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2013-02-01
              • 1970-01-01
              • 1970-01-01
              • 2013-05-31
              • 2010-12-05
              • 2021-12-04
              • 1970-01-01
              相关资源
              最近更新 更多