兜底
在工作中,我们希望遇到这样的领导,他会对你说:没事,大胆干,有什么问题找我,上边压力我帮你们顶着。当然他也是这么做。
在感情中,我们希望遇到这样的伴侣,他会对你说:没事,不想干就别干了,回家我养你,又不是养不起。当然他也是这么做。
在社交中,我们希望遇到这样的朋友,他会对你说:别慌,工作迟早能找见,找不见先来我这,管吃管住还是没问题的。当然他也是这么做。
每个人都希望在无能为力的时候,有人站出来说,别怕,还有我。
但现实大多不如意,大概率你遇到的都是以下这样的:
领导,你们注意啊,干活儿认真点,别给我惹麻烦,有事儿自己解决,别扯我身上,有好处记得我。
伴侣,咋就不想干了,不干这个干什么,你不干活吃什么,喝什么,我可养不起你。
朋友,什么?信号不好,有时间再说哈。
可能是跟程序打交道多了,不想去跟人争辩,程序会按照既定规则来执行,而且程序还有帮我们兜底的责任心。
今天我们就讲一个可靠的关键字,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. 唠唠
今天不唠了,下次吧。