finally代码块一定会执行吗?




                                                                                                                             深度解析Finally

1. 首先在大家的印象中,无论程序是否出现异常,Finally代码块是一定会执行的。这个观点可能会让大家有些失望了,答案是否定的。接下来就让我来详细的给大家讲解一下吧。

案例1.

     

   

其执行结果为:如下图(数组下标越界,没有下标为3这个索引),我们可以看到并没有执行finally代码块中的打印语句

            

 

另外,当我们把注释掉的语句前面的注释符给去掉时,运行代码,其结果如下图,也没有执行finally代码块中的打印语句

    

通过以上例子可以看出,finally代码块中的打印语句都没有被执行,这是为什么呢?

这是因为这两个例子都在try代码块之前就结束了temp()方法,try代码块并没有得到执行,所以finally中的代码块也不会得到相应的执行。只有在try代码块得到执行的情况下,finally代码块才会得到执行。

2. 那么问题又来了,是不是只要try代码块得到执行了,finally代码块才一定会执行呢?

   可能又会让你们失望了,答案时不一定会执行,这是为什么呢,请看如下代码

 

 

执行结果为:可以看到只打印了try代码块中的语句,finally代码块中的语句并没有打印,这是因为System.exit(0);它表示退出当前Java虚拟机,一旦退出Java虚拟机,任何代码都不会再执行。

 

3. 你们会说,写程序一般都不会写System.exit(0);来退出Java虚拟机,那么是不是不写System.exit(0)finally代码块就一定会得到执行呢?

可能还是会让你们失望了,答案时不一定的,这又是为什么?来看这段文字,估计你应该会明白一些。

如果当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行。还有更极端的情况,就是在线程运行 try 语句块或者 catch 语句块时,突然死机或者断电,finally 语句块肯定不会执行了。

下面来让我们讲解一下,再排除以上finally代码块不得到执行的情况外,finally代码块与try代码块和catch代码块的执行顺序,当try和catch代码块中有return语句时,又是一个什么样的情况。

 

 

执行结果为:可以看到finally代码块中的打印语句在try代码块中的return 0;之前被执行

 

 

当把第15行的注释符去掉之后,其执行结果为:可以看到finally代码块在catch代码块中的return 2;语句之前被执行

 

4. 通过以上例子,是不是觉得自己对finally已经掌握颇深了呢?别急,还有一些是你不了解的,请听我来给你详细的讲解一下。请看如下的例子

    


其执行结果为:想必看了执行结果应该容易理解,因为finally代码块要在try代码块中的return 1;之前执行,所以当执行到finally代码块中的return 3时,temp()方法就结束了,并返回一个3.

 

 

再来看一个例子,大家可以先不看执行结果,想一下它的执行结果会是什么样子的

 

 

执行结果为:

 

 

是不是觉得结果有点出乎意料,最后一句输出语句的执行结果应该为2,可为什么是1呢?而且finally代码块中语句的确在try代码块return i之前得到执行了,finally代码块中的i也确实变成了2,可是为什么main函数打印出来的结果却是1呢?

通俗的说就是:先会把try或者catch代码块中的返回值保留,再来执行finally代码块中的语句,等到finally代码块执行完毕之后,在把之前保留的返回值给返回出去。  

(请注意,前对于这条规则(保留返回值),只适用于 returnthrow语句,不适用于breakcontinue语句,因为它们根本就没有返回值。)

这样就能够理解为什么打印的是1,而不是2了,这是因为try代码块中先会保留return返回的1,然后执行finally代码块中的++ii的值虽然变成了2,可是保留的值还是1,没有变,所以等到finally代码块执行完毕之后,try代码块就会把保留值1给返回出去

5. 有了上面的讲解,我们在来看一下下面的这几个例子

     

其执行结果为:

  

    






  

   其执行结果为:


      

以上的两个例子比较好理解,接下来看一下下面这个例子,大家可以先不看执行结果,来想一下它的执行情况

 

其执行结果为:

    

是不是觉得很奇怪,num()方法中的打印语句居然在finally代码块中的打印语句之前被执行,而finally代码块的打印语句又在num()方法中的return 2;之前被打印,这又是为什么呢?

其实     return num();     等同于下面这段代码

 

所以就会先打印num()方法中的语句,后打印finally代码块中的语句.

通过以上讲解,是不是对finally有了一个更深的了解了呢!


原文链接:http://blog.csdn.net/jiasanshou/article/details/6996932



猜你喜欢

转载自blog.csdn.net/weixin_39778570/article/details/80821116