• try-cathc-finally


    兜底

    在工作中,我们希望遇到这样的领导,他会对你说:没事,大胆干,有什么问题找我,上边压力我帮你们顶着。当然他也是这么做。

    在感情中,我们希望遇到这样的伴侣,他会对你说:没事,不想干就别干了,回家我养你,又不是养不起。当然他也是这么做。

    在社交中,我们希望遇到这样的朋友,他会对你说:别慌,工作迟早能找见,找不见先来我这,管吃管住还是没问题的。当然他也是这么做。

    每个人都希望在无能为力的时候,有人站出来说,别怕,还有我。

    但现实大多不如意,大概率你遇到的都是以下这样的:

    领导,你们注意啊,干活儿认真点,别给我惹麻烦,有事儿自己解决,别扯我身上,有好处记得我。

    伴侣,咋就不想干了,不干这个干什么,你不干活吃什么,喝什么,我可养不起你。

    朋友,什么?信号不好,有时间再说哈。

    可能是跟程序打交道多了,不想去跟人争辩,程序会按照既定规则来执行,而且程序还有帮我们兜底的责任心。

    今天我们就讲一个可靠的关键字,finally

    一、try-catch-finally

    一般写法,当然,我们只是举例说明我们使用finally的场景,而不是说必须加finally

    // 步骤1.do something
    try {
        // 步骤2.do something
    } catch (ExceptionA a) {
        // 步骤3.do something
    } catch (ExceptionB b) {
        // 步骤4.do something
    } finally {
        // 步骤5.do something 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    大家都很熟悉这样的写法,经常会有人出一些闹经急转弯的题,这里我也简单来解答一下。

    1. 什么时候finally不执行

    在步骤1中有异常抛出,有return的时候,都不执行finally

    其实这是一句废话,根本没有进try-catch-finally体系,他怎么可能执行嘛,但是就有人考你,记住这个坑就好

    在步骤1、2、3、4中如果有系统级别错误,或者系统级别退出后就不执行finally,很容易理解,

    系统崩溃了,当然任何步骤都不会执行了。比如断电,cpu烧了等。

    在系统没问题的时候,系统很听话的,你说你退出吧(system.exit(0)),他马上退出,一条语句都不愿意多给你执行的。

    public static void main(String[] args) {
        try {
            System.out.println("try");
            throw new RuntimeException("异常");
        } catch (Exception e) {
            System.out.println("catch");
            System.exit(0);
        } finally {
            System.out.println("finaly");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出结果可以看到finally没有执行:

    在这里插入图片描述

    2. 执行哪个return(或者是程序执行顺序)

    这个虽然简单,但是很多类型。

    咱们就不聊try前边的代码了,咱们只聊try-catch-finaly的代码

    情况1:

    执行顺序:try->catch->finally->other->returnOther

    当然,try没有异常是不执行catch的,这个点下边几种情况就不赘述了。

    try {
        System.out.println("try");
        throw new RuntimeException("错误");
    } catch (Exception e) {
        System.out.println("catch");
    } finally {
        System.out.println("finally");
    }
    System.out.println("other");
    return "returnOther";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    情况2:

    执行顺序:try->finally->returnTry

    try里有return且没有在return前抛异常,那么就不会执行returnOther

    说明:

    在这里说明一下,我这里写了finally->returnTry .

    但是我们finally的代码块是在return语句执行之后,返回之前执行的。我这里的returnTry意思是返回,而非执行return。

    流程是这样的:return代码执行存储返回值X->finally代码块执行->返回存储的值X 下边情况也类似,自己体会。

    如果我们看编译后的字节码,我们会发现,return后store,然后执行一系列操作(finally代码),然后再执行load

    在这里插入图片描述

    下边的catch返回也类似。

    try {
        System.out.println("try");
        return "returnTry";
    } catch (Exception e) {
        System.out.println("catch");
    } finally {
        System.out.println("finally");
    }
    System.out.println("other");
    return "returnOther";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如果有异常,是这样子的:

    try->catch->finally->other->returnOther

    try {
        System.out.println("try");
        int j = 10/0;
        return "returnTry";
    } catch (Exception e) {
        System.out.println("catch");
    } finally {
        System.out.println("finally");
    }
    System.out.println("other");
    return "returnOther";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    情况3:

    执行顺序:try->catch->finally->returnCatch

    try {
        System.out.println("try");
        int j = 10/0;
    } catch (Exception e) {
        System.out.println("catch");
        return "returnCatch";
    } finally {
        System.out.println("finally");
    }
    System.out.println("other");
    return "returnOther";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    情况4:

    执行顺序:try->finally->returnFinally

    try {
        System.out.println("try");
        return "returnTry";
    } catch (Exception e) {
        System.out.println("catch");
    }finally {
        System.out.println("finally");
        return "returnFinally";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    情况5:

    执行顺序:try->catch->finally->returnFinally

    try {
        System.out.println("try");
        throw new RuntimeException("异常");
    } catch (Exception e) {
        System.out.println("catch");
        return "returnCatch";
    }finally {
        System.out.println("finally");
        return "returnFinally";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    情况6:

    执行顺序:try->catch->finally->returnFinally

    try {
        System.out.println("try");
        int j = 1/0;
        return "returnTry";
    } catch (Exception e) {
        System.out.println("catch");
        return "returnCatch";
    }finally {
        System.out.println("finally");
        return "returnFinally";
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意:

    如果finally有return就会直接return的意思不是说不执行try或者catch里边的return,我们情况2说了,return分为两步,如果finally里边有return,那么try,catch里的return只会执行第一步,例如:

    执行顺序:try->try里return代码->finally->returnFinally

    package test;
    
    /**
     * @author 木子的昼夜编程
     */
    public class TryCatchFinayTest {
        public static void main(String[] args) {
            System.out.println(test04());
        }
        public static String test04() {
            try {
                System.out.println("try");
                return get();
            } catch (Exception e) {
                System.out.println("catch");
                return "returnCatch";
            }finally {
                System.out.println("finally");
                return "returnFinally";
            }
        }
    
        private static String get() {
            System.out.println("try里return代码");
            return "嘿嘿";
        }
    
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    3.返回什么值

    有下边两个程序,大家看一下输出值是什么:

    age=?
    i=?

    package test;
    
    /**
     * @author 木子的昼夜编程
     */
    public class TryCatchFinayTest {
        public static void main(String[] args) {
            System.out.println("age:"+test01().age);
            System.out.println("i:"+test02());
        }
        // 返回对象(实际是返回对象的引用)
        public static Person test01() {
            Person p = new Person();
            try {
                p.age = 18;
                return p;
            } catch (Exception e) {
                p.age = 19;
            }finally {
                p.age = 20;
            }
            return p;
        }
        // 返回基本类型
        public static int test02() {
            int i = 0;
            try {
                i = 18;
                return i;
            } catch (Exception e) {
                i = 19;
            }finally {
                i = 20;
            }
            return i;
        }
    
    }
    
    class Person{
        int age;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    没错:

    age=20

    i=18

    i=18这个应该没啥疑问,如果对age=20有疑问的,你要理解,test01()返回的是对象的引用

    如果我们看编译后的字节码,你会发现是用的areturn (从当前方法返回对象的引用),而test01()是用的ireturn(从当前方法返回int),不管在哪儿,只要修改了引用对象的值,其他地方都是有感知的。

    当然了,例如String、基础类型包装类(Integer等),返回也是areturn,但是我们finally修改了,返回是不生效的。

    4. 唠唠

    今天不唠了,下次吧。

  • 相关阅读:
    视频加密的误解
    基于ssm设备租赁报修借用管理系统java项目源码
    用遗传算法求解多旅行推销员问题的新方法
    【亚马逊云科技产品测评】活动征文|AWS Linux配置node环境并部署Vue项目
    react配置项目路径别名@
    深入了解多分类混淆矩阵:解读、应用与实例
    【Linux】进程控制 —— 进程创建/终止/等待
    RIS 系列 Beyond One-to-One: Rethinking the Referring Image Segmentation 论文阅读笔记
    [附源码]Python计算机毕业设计SSM开放式实验室预约系统(程序+LW)
    [.NET/WPF] 设置按钮, 以及其他任何包含边框的控件的圆角
  • 原文地址:https://blog.csdn.net/qq_36291682/article/details/127593008