try-cathc-finally

发布于:2022-10-29 ⋅ 阅读:(389) ⋅ 点赞:(0)

兜底

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

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

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

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

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

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

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

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

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

今天我们就讲一个可靠的关键字,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. 什么时候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");
    }
}

输出结果可以看到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";

情况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";

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

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";

情况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";

情况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";
}

情况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";
}

情况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";
}

注意:

如果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 "嘿嘿";
    }

}


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;
}


没错:

age=20

i=18

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

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

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

4. 唠唠

今天不唠了,下次吧。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到