@linux1s1s
2019-02-15T13:05:10.000000Z
字数 2785
阅读 2305
Java 2015-11
对于一般常规例子,我们直接给出小结
(假设有返回值)
在不抛出异常的情况下,程序执行完 try 里面的代码块之后,该方法并不会立即结束,而是继续试图去寻找该方法有没有 finally 的代码块。
在抛出异常的情况下,程序执行完 catch 里面的代码块之后,该方法并不会立即结束,而是继续试图去寻找该方法有没有 finally 的代码块。
对于上面给出的小结,我们来个例子佐证一下
public class TryCatchFinnal {public static final String getName() {String name = "";try {name = "try";return name;} catch (Exception e) {name = "catch";return name;} finally {name = "finally";}}}
测试用例
public class TestCase {public static void main(String[] args) {System.out.println(TryCatchFinnal.getName());}}
运行结果

哇偶,根据上面的小结,是不是很奇迹为啥返回结果不是 finally ?
为了一探究竟,我们直接看编译出来的字节码好了
public static final java.lang.String getName();Code:Stack=1, Locals=4, Args_size=00: ldc #16; //String2: astore_03: ldc #18; //String try5: astore_06: aload_07: astore_38: ldc #20; //String finally10: astore_011: aload_312: areturn13: astore_114: ldc #22; //String catch16: astore_017: aload_018: astore_319: ldc #20; //String finally21: astore_022: aload_323: areturn24: astore_225: ldc #20; //String finally27: astore_028: aload_229: athrowException table:from to target type3 8 13 Class java/lang/Exception3 8 24 any13 19 24 anyLineNumberTable:line 5: 0line 8: 3line 9: 6line 15: 8line 9: 11line 10: 13line 12: 14line 13: 17line 15: 19line 13: 22line 14: 24line 15: 25line 16: 28LocalVariableTable:Start Length Slot Name Signature3 27 0 t Ljava/lang/String;14 10 1 e Ljava/lang/Exception;StackMapTable: number_of_entries = 2frame_type = 255 /* full_frame */offset_delta = 13locals = [ class java/lang/String ]stack = [ class java/lang/Exception ]frame_type = 74 /* same_locals_1_stack_item */stack = [ class java/lang/Throwable ]
通过字节码,我们发现,在try语句的return块中,return 返回的引用变量(t 是引用类型)并不是try语句外定义的引用变量t,而是系统重新定义了一个局部引用t’,这个引用指向了引用t对应的值,也就是try ,即使在finally语句中把引用t指向了值finally,因为return的返回引用已经不是t ,所以引用t的对应的值和try语句中的返回值无关了。
所以我们有必要补充一下
public class TryCatchFinnal {public static final String getName() {String name = "";try {name = "try";Integer.parseInt(null);return name;} catch (Exception e) {name = "catch";return name;} finally {name = "finally";}}}

而如果直接在finally语句块中返回这个值,显而易见返回值是finally。
public class TryCatchFinnal {@SuppressWarnings("finally")public static final String getName() {String name = "";try {name = "try";Integer.parseInt(null);return name;} catch (Exception e) {name = "catch";return name;} finally {name = "finally";return name;}}}

