finally 语句里还有大玄机,和我们想象的不一样

今天我们来探讨 Java 中的 finally 语句,通常用来关闭资源
但是有些情况下,在 finally 语句修改了值,可能对结果没有什么影响,我们来看看代码,是怎么回事。

我们看一段代码,先在心里想一个答案,然后继续往下看

public class TryTest {

    private static int test() {
        int x = 1;
        try {
            System.out.println("A");
            return ++x;
        } catch (Exception e) {
            System.out.println("D");
        } finally {
            System.out.println("B");
            ++x;
        }
        System.out.println("C");
        return x;
    }

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

答案是:
A
B
2

疑惑:为什么不是 AB3,又为什么不是ABC3?

带着疑惑,我们通过 Debug 看下执行过程

(1)首先执行 try 中的语句,此时 x = 1

在这里插入图片描述
(2)然后执行 return ++x; 此时x = 1
在这里插入图片描述
(3)由于没有抛出异常,此时不执行catch语句,继续执行 finally 的语句
在这里插入图片描述
(4)继续执行
在这里插入图片描述
(5)继续执行,会发现,再次回到 try {…} 中的代码,停留在 return ++x;
在这里插入图片描述
(6)再继续执行,就已经返回了,但返回值是 2,不是刚刚的3
在这里插入图片描述
System.out.println(“B”); return x; 这两句压根就没有执行,返回值也不是我们预期的3,WF ?

这是怎么回事?
官方给出的解释

如果 try 语句里有 return,那么代码的行为如下:

  1. 如果有返回值,就把返回值保存到局部变量中
  2. 执行 jsr 指令跳到 finally 语句里执行
  3. 执行完 finally 语句后,返回之前保存在局部变量表里的值。(虽然执行 ++x 后,x的值为3,但是返回保存在局部变量中的x = 2)

根据以上的 debug 调试以及解释说明就可以知道返回x为什么是2了。

当执行到 return ++x; jvm 再执行完 ++x 后会在局部变量表里另外分配一个空间来保存当前的 x 值
注意,现在还没有把返回值给 result,而是继续执行 finally 语句里语句。等执行完后再把之前保存的值(是2,不是3)返回给 result

总结一下

finally 语句在 try 或 catch 中的 return 语句执行之后,返回之前执行。
且 finally 里的修改语句不一定影响 try 或 catch 中 return 已经确定的值。
若 finally 里也有 return 语句,则覆盖 try 或 catch 中的 return语句直接返回。

另外,还有两种情况,finally 语句不一定会执行的

1、 try 语句没有被执行到,比如 在 try 语句执行之前就返回了,此时 finally 语句不会被执行的
2、try 块中有 System.exit(); 这样的语句,这个语句会终止 Java 虚拟机,连虚拟机都停了,当然 finally 语句也不会被执行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值