通過字節碼分析try finally(五)

public class Test {
    public static void main(String[] args) {
        int i = show();
        System.out.println(i);

    }

    public  static int show(){
        int i = 10 ;
        try{
            return i;
        } finally {
            i = 32;
        }
        System.out.println("沒有執行到這裏....");
        return i;
    }

}

這裏需要思考幾個問題:

  1. 是不是執行到第一個return i ;就方法返回值並結束
  2. finally代碼塊是否執行了
  3. 是否打印了輸入的字符串

通過執行javap -v Test.class命令 可以查看class字節碼,下面只拿出了重點需要講解的show()方法

 public static int show();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=3, args_size=0
         0: bipush        10    //常量10壓入操作棧的棧頂
         2: istore_0     //保存到局部變量表的slot_0中
         3: iload_0  //加載slot_0的值10 載入到操作棧的棧頂
         4: istore_1    //把當前操作數棧的棧頂值10又存放到了局部變量中slot_1的位置(沒有名字)
         5: bipush       //常量32壓入操作棧的棧頂  
         7: istore_0   //把棧頂的值32保存到局部變量表中slot_0的位置
         8: iload_1   //加載slot_1元素的值10 載入到操作數棧的棧頂
         9: ireturn  //返回棧頂的10
        10: astore_2 //根據異常表中的信息 發生異常則執行此處
        11: bipush       //常量 32 壓入操作棧的棧頂
        13: istore_0  //保存到局部變量表的slot_0中
        14: aload_2  //加載異常對象的引用
        15: athrow   //拋出異常
      Exception table:   //異常表   from to 表示捕獲字節碼中2-3的代碼,然後根據type類型進行匹配,如果匹配成功則執行第10的位置
         from    to  target type
             3     5    10   any
      LineNumberTable:
        line 11: 0
        line 13: 3
        line 15: 5
        line 13: 8
        line 15: 10
        line 16: 14
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            3      13     0     i   I
      StackMapTable: number_of_entries = 1
        frame_type = 255 /* full_frame */
          offset_delta = 10
          locals = [ int ]
          stack = [ class java/lang/Throwable ]
}

通過上面的分析可以看出 :當只有try塊中包含return,則先會把返回的值存放到一個臨時的局部變量表的位置,然後在執行finally塊中的代碼,雖然最終對i的值做了修改,但返回的值是之前已經臨時保存起來的,並不影響返回結果。

  1. 代碼在執行到try 裏面的return並沒有馬上結束方法
  2. finally語句總會執行
  3. 沒有打印輸入,說明在try 中的return在執行完finally代碼塊後就返回值並結束方法

   

public class Test {
    public static void main(String[] args) {
        int i = test() ;
        System.out.println(i);
    }
    public static int test() {
        int a = 10;
        try {
        int  c = 1/0;
            return a;
        } catch (Exception e) {
            a = 22;
            return a ;
        } finally {
            a =33;
            return a ;
        }
    }

}

 

  通過字節碼的分析,大家通過測試還可以得出以下結論

  1. try catch finally中都包含return的時候,finally裏面的return最牛B,返回的是finally代碼塊裏面壓入操作棧的值
  2. finally中使用return語句,會屏蔽錯誤的發生,通過字節碼文件就會發現沒有了athrow這行指令
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章