System.exit,最后是代码分析

时间:2016-03-01 11:22:10

标签: java

请帮我理解下面的代码,

案例1:

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

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

  

无法访问的代码

案例2:

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

上面的代码不会抛出任何编译/运行时错误,但是当我运行程序时只退出。

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

7 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:1)

案例1:

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

这是无法访问的,因为编译器可以看到您从该方法返回,因此不会再运行任何代码。

案例2:

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

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

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

  

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

并且exit()投掷的唯一例外是SecurityException

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

无论您是拨打System.exit()还是explodeMyPC()(这可能实际上是Kaboom您的电脑)都无关紧要。

答案 5 :(得分:1)

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

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

编译器对System.exit的行为方式一无所知

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

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

答案 6 :(得分:1)

这是运行时与编译时间的区别。在第一种情况下,Java编译器阻止成功编译,因为语句System.exit(1)永远不会被执行(如下所示:如果执行return语句,则无法执行任何其他语句由于这个原因,Java规范禁止使用这种代码,编译器只是禁止使用这种代码。编译器知道return语言特性,它强制要求没有其他代码。但是,System.exit(1)被视为方法调用,就像任何其他API方法一样。

在第二种情况下,编译器不会将System.exit()视为处理return;语句的方式,这就是语句的效果仅留给运行时的原因。当此代码在运行时执行时,System.exit(1);行被命中并且VM退出,从而没有机会到达return语句。但是,编译器认为这是完全合法的代码。