Try,Catch,Finally三塊中如果有Return是怎么個運行順序


     今天看一個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;

 

 

但是 “IL_001c: leave.s IL_0027 ”  leave.s 還沒看明白怎么回事?有相關熟悉的人,請指點,謝謝!

 

另外問題提到:有多個return的情況,返回哪個return的結果?  我試了一下,沒有發現允許執行多次return的可能!如果有請不吝指出!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM