今天看一個Java SSH的面試題,題目大概意思是:try、catch中存在return語句,還會執行finally塊嗎?如果執行,是return先執行還是finally先執行?如果有多個return語句,結果如何?
看了以後我還真犯嘀咕,做了軟體開發這些年,還沒認真思考過則個問題,于是趕緊寫個測試測試代碼如下:
1 class Program
2 {
3 public static int a = 0;
4 static void Main(string[] args)
5 {
6 var result = GetValue();
7 }
8
9 public static int GetValue()
10 {
11 try
12 {
13 a = 2;
14 throw new Exception();
15 }
16 catch (Exception ex)
17 {
18 a = 3;
19 return a;
20 a = 4;
21 }
22 finally
23 {
24 a = 5;
25 }
26 }
27 }
為了探究個明白,使用ILSpy工具檢視IL代碼, GetValue()的IL代碼如下:
1 .method public hidebysig static
2 int32 GetValue () cil managed
3 {
4 // Method begins at RVA 0x2064
5 // Code size 42 (0x2a)
6 .maxstack 1
7 .locals init (
8 [0] class [mscorlib]System.Exception ex,//定義Exception類型變量 ex
9 [1] int32 CS$1$0000 //定義int32類型變量 CS$1$000
10 )
11
12 IL_0000: nop //No Operation 沒有任何操作
13 .try
14 {
15 .try
16 {
17 IL_0001: nop
18 IL_0002: ldc.i4.2 //把int32 類型的資料2 推入計算堆棧上
19 IL_0003: stsfld int32 ConsoleApplication1.Program::a //用計算堆棧的值替換靜态字段a的值
20 IL_0008: newobj instance void [mscorlib]System.Exception::.ctor() //執行個體化Exception對象,并将對象推入到計算堆棧上
21 IL_000d: throw //引發目前位于計算堆棧上的異常對象
22 } // end .try
23 catch [mscorlib]System.Exception
24 {
25 IL_000e: stloc.0 //從計算堆棧的頂部彈出目前值(Exception對象)并将其存儲到索引 0 處的局部變量清單中
26 IL_000f: nop
27 IL_0010: ldc.i4.3 //把整數類型3推入計算堆棧上
28 IL_0011: stsfld int32 ConsoleApplication1.Program::a //用計算堆棧的值置換靜态變量a的值
29 IL_0016: ldsfld int32 ConsoleApplication1.Program::a //将靜态字段a的值推入計算堆棧上
30 IL_001b: stloc.1 //從計算堆棧的頂部彈出目前值,并将其存儲到索引 1 處的局部變量清單中
31 IL_001c: leave.s IL_0027 //退出受保護的代碼區域,無條件将控制轉移到目标指令 [ leave.s 指令清空計算堆棧并確定執行周圍适當的 finally 塊。]
32 } // end handler
33 } // end .try
34 finally
35 {
36 IL_001e: nop
37 IL_001f: ldc.i4.5 //把整數5推入計算堆棧上
38 IL_0020: stsfld int32 ConsoleApplication1.Program::a //用計算對象韓的值置換靜态變量a的值
39 IL_0025: nop
40 IL_0026: endfinally //将控制從異常塊的 fault 或 finally 子句轉移回公共語言結構 (CLI) 異常處理程式。
41 } // end handler
42
43 IL_0027: nop
44 IL_0028: ldloc.1 //将索引 1 處的局部變量加載到計算堆棧上
45 IL_0029: ret //從目前方法傳回,并将傳回值(如果存在)從調用方的計算堆棧推送到被調用方的計算堆棧上
46 } // end of method Program::GetValue
通過IL代碼和相關的注釋,基本可以看出他們的執行流程,猜測出這個方法傳回的結果以及靜态變量a最後的值是多少。
最後GetValue()方法傳回的結果是3;靜态變量a的值是5;
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiInBnauUzM1czM5kjN0UTM4EjMx8CXyEDNxAjMvwlM4czM5EzLcd2bsJ2Lc12bj5ycn9Gbi52YuAzcldWYtl2Lc9CX6MHc0RHaiojIsJye.jpg)
但是 “IL_001c: leave.s IL_0027 ” leave.s 還沒看明白怎麼回事?有相關熟悉的人,請指點,謝謝!
另外問題提到:有多個return的情況,傳回哪個return的結果? 我試了一下,沒有發現允許執行多次return的可能!如果有請不吝指出!