首页 > 代码库 > 关于java的10个谎言之finally

关于java的10个谎言之finally


经常在面试题中会看到:exit、finally、return的提问,这也是考察个人的基础知识。


一般(注意我的措辞‘一般’)我们都知道exit()是退出虚拟机,那么一旦调用了exit,则不管什么

return 、finally统统忽略不计,但前段时间看到了一篇博文“关于java的10个谎言”(搜了一下,好多

地方都有,也不知道谁是"首发"),这里要小记一下第一个问题(System.exit(0)会跳过finally的执

行?)的思考。


1、三者一般执行顺序

    a、return,表示方法执行返回或者结束方法运行,其实就是方法退出栈执行

    b、exit(0) ,退出虚拟机(一般认为就立马结束虚拟机生命)

    c、finally ,一般直接跟在try块或者catch块后面,在try或catch语句块中控制转移语句之前执行。

    eixt,很好理解,那return与finally呢?可以这样通俗的理解:

    在面向对象程序执行过程其实就是各种对象之间通信,对象之间的通信不就是方法调用吗,是的,所以程序执行就是一个个方法的运行,所有方法运行完了,程序也就结束了,而finally只是一个语句,那么他势必是属于某个方法的(事实是,编译器在编译finally块的时候也只是这么做的),而return是方法的结束语句,这样一来,二者就转化为顺序执行了——先finally后return(方法都要退出栈了,还不执行finally,等待何时 ?)。

  

   其实上面的只是帮助理解,本质上,finally块在虚拟机编译处理的时候,会将finally块的语句插入到try

或者catch语句块中的控制转移语句之前,而return就是控制转移语句之一,所以,当二者同时出现

时,finally语句块会被编译器插如到return之前 。


2、System.exit(0)会跳过finally的执行?  真的吗?

     上面对三者的执行顺序做了简单总结,但是运行如下代码试试,看exit后为啥还执行finally?

public static void main(String[] args) {
        
        System.setSecurityManager(new SecurityManager(){

            @Override
            public void checkExit(int status) {
                throw new ThreadDeath();
            }
        });

        try {
            System.exit(0);
        } finally{
            System.out.println("in finally block ");
        }
    }


  执行结果可能颠覆了前面说的:exit后其他都不执行,其实,前面说的是一般情况,而且99%的情况都

是那样的顺序,只是上面的代码耍了小心机(或者说我们没仔细探究exit方法)。


上面代码之所以会输出“in finally block”,是因为前面设置的SecurityManager中覆盖了checkExit方法,导致虚拟机并没有退出,为什么呢,请看分析:

     其实,这一切都是因为exit方法的实现过程,以下片段为Runtime 类中exit方法源码:

 public void exit(int status) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkExit(status);
        }
        Shutdown.exit(status);
    }

   main方法开始自上而下执行,首先设置了一个安全管理器实例,接着调用System.exit(0) ,调用时执行上面的exit方法,运行环境获取到了我们自定义安全管理器,并开始调用覆盖的方法,checkExit ,但checkExit方法抛出了error(不是exception,请看ThreadDeath类),导致exit的中Shutdown.exit()调用失败,从而导致虚拟机并没有退出,那么finally当然要执行了。


   经此,看来我们以后在学习过程中一定要看一手资料,多看细节实现。

 

  

       

  


关于java的10个谎言之finally