1.在学习异常时,我们学习到了处理异常的try——catch语句,以及finally关键字。
try{ // 有可能发生异常的代码段 (捕获异常)
}catch(异常类型1 对象名1){ // 异常的处理操作
}catch(异常类型2 对象名2){ // 异常的处理操作
} ... finally{ //后置处理代码
finally用于try-catch后用来必须执行末段程序
****finally有一个很重要的特点
public static void main(String[] args) {
try {
test();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void test() throws Exception {
try {
throw new Exception("lalalala");
}catch (RuntimeException e){
e.printStackTrace();
}finally {
System.out.println("finally");
}
}
输出:
finally
java.lang.Exception: lalalala
at helloworld.exception.FinallyTeach.test(FinallyTeach.java:15)
at helloworld.exception.FinallyTeach.main(FinallyTeach.java:7)
结论:
异常如果没有被捕获,会执行finally的代码
public static void main(String[] args) {
try {
test2();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void test2() throws Exception {
try {
throw new RuntimeException("abcd");
}catch (RuntimeException e){
e.printStackTrace();
}finally {
System.out.println("finally");
}
}
输出:
finally
java.lang.RuntimeException: abcd
at helloworld.exception.FinallyTeach.test2(FinallyTeach.java:25)
at helloworld.exception.FinallyTeach.main(FinallyTeach.java:7)
结论: 如果异常被捕获,依然会执行finally里的代码
最终结论:
1.无论异常是否被捕获,finally的代码一定会被执行。
2.finally里适合存放释放资源、后续处理的代码
2.通常释放资源等操作放在finally中,比如流的关闭
finally块只能定义在异常处理机制的最后
* 可以直接跟在try后面或者最后一个catch之后.
* finally可以保证只要程序运行到try当中,那么无论
* try当中的代码片段是否出现异常,finally块里面的
* 代码都必然执行.
* 通常把释放资源等操作放在finally中,比如流的关闭.
- finally块不管异常是否发生,只要对应的try执行了,则它一定也执行。只有一种方法让finally块不执行:System.exit()。因此finally块通常用来做资源释放操作:关闭文件,关闭数据库连接等等。
- finally块没有处理异常的能力。处理异常的只能是catch块。
3.try-catch-finally的执行顺序
- 首先是try执行,如果发生异常,那么catch直接捕获异常,最后执行finally。但是如果catch抛出了一个异常,那么不会立刻回溯到上一个方法,而是仍然执行finally。
- finally之前的所有代码,正常执行,但是return返回之类的,全部被“卡”了下来,只有在finally执行之后,才能继续执行。
- finally是无论怎样一定在方法的最后结束前执行的。搜了一些资料,是说finally会在方法结束之前执行,而之前所有的执行,包括return,全部都停留在栈中,而finally最终执行后才继续。所以本应该回溯的代码执行完finally后才回溯,return的时候也是等finally执行之后再执行。
- finally就是最终执行,如果有return,直接从finally返回。
- JVM规范中有:如果try语句里面有return,那么先将值保存到局部变量中,然后执行finally语句,返回之前保存在局部变量中的值。
所以综上总结:当try——catch中有retuen时
(1)如果finally块代码中没有return语句时,则会先执行finally块中代码之后,再执行try块中return语句。
(2)如果finally块中有return语句时,则程序中的finally块代码中的return语句将会覆盖程序中别处的return语句,最终程序返回给调用者的是finally块代码中return的值。
4.返回值
一个方法内部定义的变量都是存储在栈中,如果当前这个函数结束之后,与其对应的栈就会被回收,此时在其方法体重定义的变量都将不存在了,因此在return返回时,并不是返回变量的值,而是提前复制一份,然后将其复制的再返回。
- 对于基本数据类型来说,finally块中改变return的值并不会对返回值有任何的影响。
- 而对引用类型来说,finally改变的是引用引向堆中被修改的内存,所以return的值就会是堆中被修改的值。