try—catch—finally的使用
例1:
- <span style="font-size:14px;">public static int func (){
- try{
- return 1;
- }catch (Exception e){
- return 2;
- }finally{
- return 3;
- }
- }</span>
输出结果为:3
例2:
- <span style="font-size:14px;">public class Test {
- public static void main(String[] args) {
- System.out.println(fun());
- }
- @SuppressWarnings("finally")
- public static int fun(){
- int i = 0;
- try{
- return i;
- }catch(Exception e){
- return ++i;
- }finally{
- ++i;
- }
- }
- }</span>
虽然程序在执行return返回之前i的值已经变为1,但是输出结果为::0
总结:
return在try-catch-finally中: 1、不管有木有出现异常,finally块中代码都会执行; 2、当try和catch中有return时,finally仍然会执行; 3、finally语句是在try或catch中的return语句执行之后返回之前执行的且finally里
的修改语句不会影响try或catch
中return已经确定的返回值
(因为会把try或catch中return要返回的值先保存起来,
然后再执行finally中的语句,
所以不管finally中的代码怎么样,
返回的值都不会改变,仍然是之前保存的值);
若finally里也有return语句则覆盖try或catch中的return语句直接返回
Java语言中try-catch-finally的执行顺序
- public static int func (){
- try{
- return 1;
- }catch (Exception e){
- return 2;
- }finally{
- return 3;
- }
- }
-------------------分割线----------------
finally的作用
对于一些代码,无论try块中的异常是否会抛出,它们都得执行。这通常适用于内存回收之外的资源清理工作(内存回收由后台GC线程自动完成),如已经打开的文件或网络连接,屏幕上画的图形,数据库连接等等。那么这些代码就可以放到finally子句内。
finally的使用
finally正常的使用大家都比较常见,但在再次抛出异常、与return结合等情况下,容易产生迷惑,所以整理为下面几节。
异常再次抛出时
finally语句总会执行,甚至在异常没有被当前异常处理程序捕获,而重新抛出给更高一层前,finally会执行,例子是《Java编程思想》里的,如图:
在return中使用finally
由于finally总会执行,所以如果在return中使用finally,就可从多个点返回,同时保证重要的、必须的工作仍旧执行,即在含有finally的函数中,从何处返回无关紧要,示例如下:
- public class TryCatchFinally{
- public static int func(int i){
- System.out.println("func");
- try{
- System.out.println("try block");
- if(i == 1) return 1;
- if(i == 2) return 2;
- if(i == 3) return 3;
- return -1;
- }catch (Exception e){
- System.out.println("catch block");
- return -2;
- }finally{
- System.out.println("finally block");
- }
- }
- public static void main(String[] args){
- for(int i=1; i <= 4; i++){
- System.out.println(func(i));
- System.out.println("-----------");
- }
- }
- }
- func
- try block
- finally block
- 1
- -----------
- func
- try block
- finally block
- 2
- -----------
- func
- try block
- finally block
- 3
- -----------
- func
- try block
- finally block
- -1
- -----------
finally的优先覆盖
这里还需要指出,finally子句有最高的控制流返回权,其可以覆盖try、catch块内的任意Exception值、return值。如下的函数,将会返回12,而不是10。
- public static int getMonthsInYear(){
- try{
- return 10;
- } finally {
- return 12;
- }
- }
- public static int getMonthsInYear(){
- try{
- throw new RuntimeException();
- } finally {
- return 12;
- }
- }
- public static int getMonthsInYear(){
- try{
- return 12;
- } finally {
- throw new RuntimeException();
- }
- }
finally不执行的特殊情况
finally子句一定会执行,除了极少的极端情况:
- 调用了
System.exit()
- Java虚拟机崩了
总结
finally子句一定会执行,如果其含有程序控制流返回的语句,如return、throw e等,那么try、catch子句的相应控制流语句会失效;反之,当finally里没有控制流返回语句时,就会返回try或catch的控制流返回处,进行正常控制流交还操作。当然,这种编程方式是极不友好的,大概也只有在面试的时候能遇到吧。
另外,参考里给的stachoverflow的链接里,有几个回答很好,比如有个牛人直接贴出了Java语言规范(JLS),有的一句话就点清,上面最后的三段代码就是参考的某个高票回答,想深入了解的请继续阅读探索。