正文
我们编写代码的时候,稍微的不注意,就会出现各种的异常。通常,我们的解决的方式是用try-catch-finally,来完成我们的异常处理。但是,我们忽略了一个细微的问题,他的执行顺序是怎么样的,如何执行的呢?
问题一:try-catch-finally哪些部分可以省略?
下面三种的书写方式都是可以的:
- try-catch-finally
- try-catch
- try-finally
也就是说,在try-catch-finally这3个部分,有两个部分是可以省略掉的,但是不能同时的省略。
问题二:执行的顺序问题:
如果我们在catch里面返回了,那么,finally还能执行吗?我们做一个简短的测试:
说明,在我们在我们返回前,finally都是可以执行的。
总结:
- finally的作用就是,无论出现什么状况,finally里的代码一定会被执行。
- 如果在catch中return了,也会在return之前,先执行finally代码块
- 而且如果finally代码块中含有return语句,会覆盖其他地方的return。
- 对于基本数据类型的数据,在finally块中改变return的值对返回值没有影响,而对引用数据类型的数据会有影响。
但是finally一定会执行吗?答案是不一定的,因为如果在try代码块中,System.exit()强制退出程序。
深入研究执行的顺序
1. 如果返回值是基本的数据类型:
上面的结果是:6 ;因为finally里面的return会覆盖掉try里面的return
2. 返回值是引用数据类型
相应的,如果是引用类型,我们可以推测一下,基本数据类型的返回值存在栈里面,那么,引用类型的返回值的引用会存储在栈里面,这个时候,我们再次进行修改返回值,会得到相应的变化的。可以参考方法的值传递以及引用传递的效果,我们就可以得到相同的结论。
最后,我们应当注意的是:return之前必须会执行finally代码块,对于finally中没有return的语句来说:如果返回值是基本数据类型,finally块中对返回值的改变不会影响返回值。因为在return之前已经将返回值的内容存储在栈中了。
如果返回值是引用数据类型,finally块中对返回值的改变会影响返回值。因为在return之前已经将引用对象的地址存储在栈中,finally块中对于引用对象值的改变会影响到返回值。