try-catch-finally | 加上return语句时执行顺序

1. try/catch/finally 介绍

try:用来捕获异常
catch:用于处理try中捕获的异常
finally:无论是否捕获或处理异常,finally块中的代码都会被执行。

  • try必须有
  • finally可以无

总结:

  • try后面必须跟catch 或者 finally 其中之一
  • try后面可以有0个或者多个catch,只能有0个或者1个finally。
  • 若try后面没有catch,则必须有一个finally
    在这里插入图片描述

2. try/catch/finally 执行顺序

在Java中,try-catch-finally语句块的执行顺序是:

  1. try块:首先执行try块中的代码。如果有return语句,则会执行并返回。
  2. finally块:无论try块中是否有return语句,都会执行finally块中的代码。这使得finally块成为一个可靠的清理代码块,它可以在方法返回之前执行任何必要的清理操作,例如关闭打开的资源。
  3. catch块:如果在try块中抛出了异常,则会跳转到相应的catch块执行。如果在catch块中也有return语句,则会执行并返回。

具体可以分以下情况讨论:

情况1:里面均无return语句

  • try里面的代码执行
    若try里面捕获了异常,则执行catch语句;否则不执行catch语句;
  • 1.若有多个catch块,当进入一个catch块,执行完毕后;
    2.即使后面还有catch块,也不会再进入其他catch块。(类似if一样选择了一个catch,其他就会跳过)
    3.如果有finally块,则进入finally块。
  • finally块一定会执行(不论释放出现异常)

情况2:里面加上return语句

  • finally中无return:当try块中或者catch块中遇到return语句时,先执行完finally里面的代码后,再执行try 或者 catch中的return语句。

    是执行try中的还是catch中的return得看try中是否有异常;
    无异常则走try块,有异常则走catch块;

  • 当finally里面有return语句:
    ①无异常时,走完try里面的代码,return也会走,然后执行finally里面的代码,最后finally里面的return会覆盖掉try之前return的结果;
    ②有异常时,走catch里面的代码,同样继续执行了catch里面的return,最后走finally里面的代码,finally里面的rerturn最终会覆盖catch的return;
    总结无论是否异常,finally不会影响try、catch里面的return语句,只是当finally里面的return会最后覆盖掉前面return的结果!!

我们来举例说明:

3. 我们来做道题

最后程序输出 i=?

	public int test() {
        int i = 0;
        try {
            i++;
            i = i / 0;
            return i++;
        } catch (Exception e) {
            i++;
            return i++;
        } finally {
            return ++i;
        }
	 }
	public static void main(String[] args) {
        System.out.println(test());
	}

大家先别看答案自己想想哦


  • 答案:4
    为什么是4呢?我前面不是说直接执行finally里面的return语句吗?
  • 解释:
    原来,我们try / catch里面的return语句在程序里面是走了这步的,只不过最后finally块里面的return语句覆盖掉了前面的。

再看一个例子

    public static int testAbc() {
        int i = 0;
        try {
            i++;
            i = i / 0;
            return i++;
        } catch (Exception e) {
            i++;
            return i=7;
        } finally {
            return ++i;
        }
    }
    //这个输出的结果就是8

原因:

首先,我们分析程序的执行流程:

  1. 初始化 i 为 0。

  2. 进入 try 块,i 自增,此时 i = 1。

  3. 执行 i = i / 0,这会抛出 ArithmeticException(因为除以0是不允许的)。

  4. 因为有异常抛出,所以程序跳转到 catch 块。

  5. 在 catch 块中,i 自增,此时 i = 2。

  6. 然后执行 return i=7,将 i 的值设为 7 并返回。

    但是,这里有一个关键点:在 Java 中,finally 块总是会被执行,无论是否有 return 语句在 try 或 catch 块中。因此,即使在 catch 块中已经有一个 return 语句,程序还是会跳转到 finally 块执行。

  7. 在 finally 块中,执行 return ++i,这将 i 的值自增并返回。由于这是在 finally 块中的返回语句,所以它会覆盖前面的所有返回语句。

因此,这个程序的结果是:8
原因:在 finally 块中,i 的值被自增了1,从7变为8,并且这个返回值覆盖了前面的所有返回值。所以,方法最终返回的是8。

举个例子

    public static int testAbc() {
        int i = 0;
        try {
            i++;
            System.out.println("我是try");
            i = i / 0;
            return i++;
        } catch (Exception e) {
            System.out.println("我是catch");
            i++;
            return i=7;
        } finally {
            System.out.println("我是finally");
            return ++i;
        }
    }

结果:
我是try
我是catch
我是finally
i=8
public static int getInt() {
    int a = 10;
    try {
        System.out.println(a / 0);
        a = 20;
    } catch (ArithmeticException e) {
        a = 30;
        return a;
        /*
         * return a 在程序执行到这一步的时候,这里不是return a 而是 return 30;这个返回路径就形成了
         * 但是呢,它发现后面还有finally,所以继续执行finally的内容,给a赋值40,但是finally并没有return;
         * 所以执行完finally后再次回到以前的路径,继续走return 30,形成返回路径之后,这里的a就不是a变量了,而是常量30
         */
    } finally {
        a = 40;
    }
	return a;
}
//输出30

public static int getInt() {
    int a = 10;
    try {
        System.out.println(a / 0);
        a = 20;
    } catch (ArithmeticException e) {
        a = 30;
        return a;
    } finally {
        a = 40;
        //如果这样,就又重新形成了一条返回路径,由于只能通过1个return返回,所以这里直接返回40
        return a; 
    }
}
//输出40

4. 最后结论

  • finally一定会执行;
  • finally一般不要写return,系统认为会是一个warning
  • finally里面的return不会影响try、catch里面的return,最后只是覆盖掉前面的return而已;
  • 26
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大龄烤红薯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值