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