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的可能!如果有请不吝指出!

原文地址:https://www.cnblogs.com/beixing/p/4160298.html