关于Java finally的一些思考

本文通过实例探讨了Java中finally块的执行时机及其与return语句的交互作用,揭示了finally块内代码总能得以执行的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先来看一段关于Java fiannlly 的定义, 百度过来的:

finally通常和try/catch语句一起使用,确保了无论是否发生异常,finally里面的代码都会被执行。


关于这个定义,我想起来之前遇到的一个面试题,如果在try语句中return了,finally里面的代码还会执行么?


public static void main(String[] args) {
try {
System.out.println("try block");

return;
} finally {
System.out.println("finally block");
}
}

打印结果为:
try block
finally block

这说明了什么? 即使是在try语句中return了,finally里的代码依然会被执行到。

那么我就想到另一个问题,finally里的代码究竟是在return前执行的,还是在return后执行的?

我设计了这样一段代码:

public class Test {

public static void main(String[] args) {
System.out.println(test());
}

public static String test() {
try {
System.out.println("try block");

return test1();
} finally {
System.out.println("finally block");
}
}

public static String test1() {
System.out.println("return statement");

return "after return";
}
}


究竟是先执行return 还是先执行finally呢?

结果是这样的:
try block
return statement
finally block
after return

可见是先调用了return的方法,然后才调用finally的代码。

这里就产生了一个悖论,既然某个方法已经return了,为什么还有代码继续执行呢?


我们看看产生的会编码:

public class Test {

// Method descriptor #6 ()V
// Stack: 1, Locals: 1
public Test();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
Line numbers:
[pc: 0, line: 2]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: Test

// Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 2, Locals: 1
public static void main(java.lang.String[] args);
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 invokestatic Test.test() : java.lang.String [22]
6 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
9 return
Line numbers:
[pc: 0, line: 5]
[pc: 9, line: 6]
Local variable table:
[pc: 0, pc: 10] local: args index: 0 type: java.lang.String[]

// Method descriptor #25 ()Ljava/lang/String;
// Stack: 2, Locals: 2
public static java.lang.String test();
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 ldc <String "try block"> [34]
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
8 invokestatic Test.test1() : java.lang.String [36]
11 astore_1
12 getstatic java.lang.System.out : java.io.PrintStream [16]
15 ldc <String "finally block"> [39]
17 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
20 aload_1
21 areturn
22 astore_0
23 getstatic java.lang.System.out : java.io.PrintStream [16]
26 ldc <String "finally block"> [39]
28 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
31 aload_0
32 athrow
Exception Table:
[pc: 0, pc: 12] -> 22 when : any
Line numbers:
[pc: 0, line: 10]
[pc: 8, line: 12]
[pc: 12, line: 14]
[pc: 20, line: 12]
[pc: 22, line: 13]
[pc: 23, line: 14]
[pc: 31, line: 15]

// Method descriptor #25 ()Ljava/lang/String;
// Stack: 2, Locals: 0
public static java.lang.String test1();
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 ldc <String "return statement"> [41]
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
8 ldc <String "after return"> [43]
10 areturn
Line numbers:
[pc: 0, line: 19]
[pc: 8, line: 21]
}


仔细看这段:

0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 ldc <String "try block"> [34]
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
8 invokestatic Test.test1() : java.lang.String [36]
11 astore_1
12 getstatic java.lang.System.out : java.io.PrintStream [16]
15 ldc <String "finally block"> [39]
17 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
20 aload_1
21 areturn



也就是说,经过编译以后,代码变成了先调用test1,并存储返回值,然后调用finally里面的代码,最后才return。


这段代码似乎没有什么现实意义,不过还是可以对java程序的理解有一定的帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值