@linux1s1s
2019-02-15T21:05:10.000000Z
字数 2785
阅读 1958
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=0
0: ldc #16; //String
2: astore_0
3: ldc #18; //String try
5: astore_0
6: aload_0
7: astore_3
8: ldc #20; //String finally
10: astore_0
11: aload_3
12: areturn
13: astore_1
14: ldc #22; //String catch
16: astore_0
17: aload_0
18: astore_3
19: ldc #20; //String finally
21: astore_0
22: aload_3
23: areturn
24: astore_2
25: ldc #20; //String finally
27: astore_0
28: aload_2
29: athrow
Exception table:
from to target type
3 8 13 Class java/lang/Exception
3 8 24 any
13 19 24 any
LineNumberTable:
line 5: 0
line 8: 3
line 9: 6
line 15: 8
line 9: 11
line 10: 13
line 12: 14
line 13: 17
line 15: 19
line 13: 22
line 14: 24
line 15: 25
line 16: 28
LocalVariableTable:
Start Length Slot Name Signature
3 27 0 t Ljava/lang/String;
14 10 1 e Ljava/lang/Exception;
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 13
locals = [ 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;
}
}
}