finally 是执行try return之前还是之后之争

来源:互联网 发布:美团抢单送外卖的软件 编辑:程序博客网 时间:2024/06/02 05:29

什么也别争了看简单的代码如下:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
    System.out.println(exceptionText());
    }
    public static int exceptionText(){
        
        try{
            int i=5;
       
            return i;
        }catch (Exception e){
            
            return 4;
        }
            
        finally{
                 return 3;
        }


非常简单的一段代码.结果返回为3;  那就有人得出 finally 是在 try return 返回之前执行 ,并且返回值覆盖.分析合情合理.

还有一种结论更为离谱,就 是try return执行 然后把返回值推进栈顶,发现还有finally 语句,然后  执行finally return 语句并覆盖掉 try return 的值,如果return 执行是不是方法结束了,

,还执行了finally 语句吗,违反java语法

结果真的是这样吗 ,看字节码如下:

  0 iconst_5     :将5推进栈顶

  1 istore_0     : 重从栈顶 pop数据 并存到本地变量中   相当了 : i=5   ,重点了来  下面并没有ireturn 语句....

  2 goto 10 (+8)   没有异常直接调转 第10行   

  5 astore_0           //pop 异常对象引用   然后还是没有ireturn 语句...

  6 goto 10 (+4) :直接调转 第10行

  9 pop

 10 iconst_3       :将3推进栈顶

 11 ireturn   //返回 pop 栈顶数据  也就是将3 返回

为什么两处都没有return 语句呢,,,,,,,,,我也不懂 ,这要问 编译器哥们..

那么如果 上面代码没有finally 语句呢  字节吗如下:

0 iconst_5    //相同不说
1 istore_0
2 iload_0      将 i里面的值推进栈顶
3 ireturn      返回5
4 astore_0
5 iconst_4
6 ireturn


这才是我们想要的结果为5:

那么在测试一下  ,如果代码 finally 语句没有 return 语句 会如何:

public static int exceptionText(){
        int i=0;
        try{
             i=5; 
            return i;
        }catch (Exception e){
            
            return 4;
        }
            
        finally{
                 i++;
        }
//        
        
    }

字节码如下:

 0 iconst_0    //同样相同不说
 1 istore_0
 2 iconst_5       
 3 istore_0
 4 iload_0    
 5 istore_3    :然后finally语句开始执行 并不是操作的 本地变量0,而是0变量复制给第四个本地变量 相当:int b=i
 6 iinc 0 by 1    :变量0自加那么 i=6
 9 iload_3       :将 b的值 推进栈顶
10 ireturn       :pop 栈顶的值返回: 返回的是b 而不是i 所以 结果了5.语句结束
11 astore_1       :异常语句执行 pop 异常变量引用 没有异常不分析..
12 iinc 0 by 1
15 iconst_4
16 ireturn      
17 astore_2
18 iinc 0 by 1
21 aload_2
22 athrow


那么就可以得出结论了:两种情况1. 如果finally 有return 语句 try 和catch 不会return 语句 而是将他们合并以finally return为基准返回. 2. 没有return 语句 先执行finally语句 在return 副本变量b,以try 和catch return 为基准返回..   所以 之前还是之后都是片面之所说,如果 认为finally 的return 语句是try的,我也没有办法。

ps:因为是静态方法所以不会传递 this 的对象参数,所以变量以0索引开始.纯属个人分析 ,不对的地方望指教.


0 0
原创粉丝点击