try-catch-finally中的坑





在 Java 语言中 try-catch-finally 看似简单,但想要真正的“掌控”它,却并不是一件容易的事。别的不说,咱就拿 fianlly 来说吧,别看它的功能单一,但使用起来却“暗藏杀机”。


坑1:finally中使用return,覆盖返回结果

若在 finally 中使用 return,那么即使 try-catch 中有 return 操作,也不会立马返回结果,而是再执行完 finally 中的语句再返回。此时问题就产生了:如果 finally 中存在 return 语句,则会直接返回 finally 中的结果,从而无情的丢弃了 try 中的返回值。

反例代码

package com.example.demo;

public class Test {

    public static void main(String[] args) {
        System.out.println("执行结果:" + test());
    }

    private static int test() {
        int num = 0;
        try {
            num++;
            return num; // num=1,此处不返回
        } catch (Exception e) {
            // do something
            System.out.println(e.getMessage());
        } finally {
            num++;
            return num;// num=2,返回此值
        }
    }

}

执行结果
在这里插入图片描述

解决方案

如果 try-catch-finally 中存在 return 返回值的情况,一定要确保 return 语句只在方法的尾部出现一次。

package com.example.demo;

public class Test {

    public static void main(String[] args) {
        System.out.println("执行结果:" + test());
    }

    private static int test() {
        int num = 0;
        try {
            num = 1;
        } catch (Exception e) {
            // do something
        } finally {
            // do something
        }
        // 确保 return 语句只在此处出现一次
        return num;
    }

}

在这里插入图片描述




坑2:finally中的代码“不生效”

反例代码

package com.example.demo;

public class Test {

    public static void main(String[] args) {
        System.out.println("执行结果:" + getValue());
    }

    private static int getValue() {
        int num = 1;
        try {
            return num;
        } finally {
            num++;
        }
    }

}

执行结果
在这里插入图片描述
解决方案

本以为执行的结果会是 2,但万万没想到竟然是 1。有人可能会问:如果把代码换成 ++num,那么结果会不会是 2 呢?很抱歉的告诉你,并不会,执行的结果依然是 1。

实际上,Java 虚拟机会把 finally 语句块作为 subroutine,直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中,待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。

因此如果在 try-catch-finally 中如果有 return 操作,一定要确保 return 语句只在方法的尾部出现一次!这样就能保证 try-catch-finally 中所有操作代码都会生效。

package com.example.demo;

public class Test {

    public static void main(String[] args) {
        System.out.println("执行结果:" + getValue());
    }

    private static int getValue() {
        int num = 1;
        try {
            // do something
        } catch (Exception e) {
            // do something
        } finally {
            num++;
        }
        return num;
    }

}

在这里插入图片描述




坑3:finally中的代码特殊情况下“不执行”

finally 中的代码一定会执行吗?

回答:正常情况下 finally 中的代码一定会执行的,但如果遇到特殊情况 finally 中的代码就不一定会执行了,比如下面这些情况:

  • 在 try-catch 语句中执行了 System.exit;
  • 在 try-catch 语句中出现了死循环;
  • 在 finally 执行之前掉电或者 JVM 崩溃了。

如果发生了以上任意一种情况,finally 中的代码就不会执行了。虽然感觉这一条有点“抬杠”的嫌疑,但从严谨的角度来说,这个观点还是成立的,尤其是对于新手来说,神不知鬼不觉的写出一个自己发现不了的死循环是一件很容易的事,不是嘛?

反例代码

package com.example.demo;

public class Test {

    public static void main(String[] args) {
        noFinally();
    }
    private static void noFinally() {
        try {
            System.out.println("我是 try~");
            System.exit(0);
        } catch (Exception e) {
            System.out.println("我是 catch~");
        } finally {
            System.out.println("我是 fially~");
        }
    }
}

执行结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值