Java中的try catch finally

一直以为自己对try catch足够了解了,但是在看到这篇博客后才意识到自己了解的仅仅是皮毛。
首先要知道f inally不是一定会执行的.下面的情况下finally就肯定不会执行的。
(1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行, 这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。
(2)在try块中有System.exit(0);这样的语句,System.exit(0);是终止Java虚拟机JVM的,连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。

其次是finally究竟是什么时候执行
finally语句是在try的return语句执行之后,return返回之前执行。这句话理解起来很费劲,我们下面用debug的截图解释。
在执行finally代码时,如果finally代码本身没有退出的语句(return或抛出异常),finally执行完毕后还会返回try或catch,由try或catch执行退出指令。
try一定要配合catch或者finally一起使用
当finally中包含return时,就不能在try和finally之后写return了,只能在catch中写return了,否则会编译通不过。
我们先看看下面的代码:

package com.xfl.exception;

/**
 * Created by XFL.
 * time on 2016/12/3 15:14
 * description:异常捕获测试
 * 在执行finally代码时,如果finally代码本身没有退出的语句(return或抛出异常),
 * finally执行完毕后还会返回try或catch,由try或catch执行退出指令
 */
public class TestException {
    public static void main(String[] args) {
        int result1 = test1();
        int result2 = test2();
        System.out.println("最终的结果是: " + result1);
        System.out.println("最终的结果是: " + result2);
    }

    /**
     * 出异常返回3,不出异常返回4.finally是在return之前执行的
     *
     * @return
     */
    private static int test1() {
        int temp = 1;
        try {
            temp += 1;
            int a = 1;
            int b = (Math.random() * 10) % 3 > 1 ? 1 : 0;
            int c = a / b;
        } catch (Exception e) {
            temp += 1;
            System.out.println(temp);
            /**
             * Return并不是让函数马上返回,而是return语句执行后,将把返回结果放置进函数栈中,
             * 此时函数并不是马上返回,它要执行finally语句后才真正开始返回。
             * finally语句是在try的return语句执行之后,return返回之前执行
             */
            return temp;
        } finally {
            /**
             * finally不是一定会执行的.
             * (1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,
             * 这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。
             *(2)在try块中有System.exit(0);这样的语句,System.exit(0);是终止Java虚拟机JVM的,
             * 连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。
             */
            temp += 1;
            System.out.println(temp);
        }
        temp += 1;
        System.out.println(temp);
        return temp;
    }

    /**
     * 出异常返回4,不出异常返回3.finally是在return之前执行的
     *
     * @return
     */
    private static int test2() {
        int temp = 1;
        try {
            temp += 1;
            int a = 1;
            int b = (Math.random() * 10) % 3 > 1 ? 1 : 0;
            int c = a / b;
        } catch (Exception e) {
            temp += 1;
            //执行return之前会先执行finally
            System.out.println(temp);
            return temp;
        } finally {
            temp += 1;
            //finally中包含return时catch中的return不起作用了
            System.out.println(temp);
            return temp;
        }
    }
}

我们分析test1方法出异常时的执行情况,出错时执行catch
这里写图片描述
此时catch中包含return语句,return并不是让函数马上返回,而是return语句执行后,将把返回结果放置进函数栈中,然后再执行finally部分
这里写图片描述
这里temp的值已经变成4了,执行完finally部分后,因为finally没有退出程序的语句,所以会返回到catch中。
这里写图片描述
虽然temp已经变成了4,但是真正返回的是3,因为这个return已经执行过了,前面已经将返回结果放到栈中了,这个时候执行return只是把栈中的值返回。(注意这里需要根据返回类型区分,如果是引用类型则在finally中对返回数据的修改是启作用的,如果是基本数据类型就不启作用了,猜测原因应该是Java的值传递,当是引用类型的时候,返回的并不是对象的内容,而是对象的引用)

现在来分析test2方法,此方法finally中包含了return语句
这里写图片描述
执行到catch中的return语句时先把返回值放入到栈中,再执行finally语句
这里写图片描述
执行到finally的return语句时,也会把返回值放入到栈中,这样前面的就不起作用了,因为finally包含程序退出语句,所以就不会再像test1方法中那样再次执行catch中的return了。这里真正返回的是4,而不是3.
这里写图片描述
上图是两个方法程序运行的结果。

现在我们来了解下Java Stacks。
所谓Java栈,描述的是一种Java中方法执行的内存模型,Java栈为线程私有,线程中每一次的方法调用(或执行),JVM都会为该方法分配栈内存,即:栈帧(Stack Frame),分配的栈帧用于存放该方法的局部变量表、操作栈(JVM执行的所有指令都是围绕它来完成的)、方法编译后的字节码指令信息和异常处理信息等,JVM指定了一个线程可以请求的栈深度的最大值,如果线程请求的栈深度超过这个最大值,JVM将会抛出StackOverflowError,注意,此处抛出的时Error而不是Exception。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值