什么时候用到finally呢?
某些事物(除内存外)在异常处理完后需要恢复到原始状态,如:开启的文件,网络连接等。
try-catch-finally 中哪个部分可以省略?
答: catch和finally可以省略其中一个 , catch和finally不能同时省略
注意:格式上允许省略catch块, 但是发生异常时就不会捕获异常了,我们在开发中也不会这样去写代码。
问题:try-catch-finally 中,如果 catch 中有 return 了,finally 还会执行吗?
答:finally中的代码会执行
finally语句在try或catch中的return语句执行之后,还是return返回之前执行呢?(最后面总结有答案)
详解:执行流程:
- 1.先计算返回值, 并将返回值存储起来, 等待返回;
- 2.执行finally代码块;
- 3.将之前储存的返回值,返回出去。
需注意:
- 1.返回值是在finally之前就确定了,并且缓存了,不管finally对该值(非引用数据类型)做任何的改变,返回的值都不会改变。
- 2.finally代码中不建议包含return,因为程序会在上述的流程中提前退出,也就是说返回的值不是try或catch的值。
- 3.如果在try或catch中停止了JVM,则finally不会执行.例如停电…, 或通过如下代码退出 JVM:System.exit(0);
finally举例1:(即使return,在准备返回值与跳出函数之间,仍会执行finally中的语句)
image.png
image.png
finally举例2:(引用数据类型和非引用数据类型的区别)
代码:(引用数据类型)
image.png
运行结果:
image.png
从结果可看出:由于 返回值是引用数据类型,在return之前准备好p(将引用地址进行备份),但是finally中通过引用数据类型的地址,修改了具体的值,所以还是显示的最终结果会更改属性值为28;
内存分析:
image.png
代码:(非引用数据类型)及运行结果:
image.png
内存分析:
image.png
为什么会产生上面这种原因,就是下面要说的关于非引用数据类型(基本数据类型)和引用数据类型的区别:
- 基本数据类型存在于栈里,那么 return备份的就是数据 。而finally改变的是栈里的数据,但是不会改变备份数据,所以返回值不变。
- 引用数据类型,数据存在于堆中开辟的空间里,而栈中存储的是堆所对应的空间地址,因此** return备份的是栈中的空间地址 **,但是finally改变的是堆中的数据,所以当return返回地址时,查找到堆中的数据就是被改变了。
总结:
1.finally代码块是在try代码块中的return语句执行之后,返回之前执行的。
2.finally代码块中的return语句覆盖try代码块中的return语句。
3.如果finally语句中没有return语句覆盖返回值,那么原来的返回值可能因为finally里的修改而改变也可能不变。传值类型的返回值:不变;传址类型的返回值:会变。
这里引入来一个新的问题,怎么判断一个变量是传值还是传址?传值:8种基本数据类型及其包装类,字符常量。传址:数组和对象。
4.try代码块中的return语句在异常的情况下不会被执行,这样具体返回哪个看情况;catch中的return执行情况与未发生异常时try中return的执行情况完全一样。