关于 finally 常考的面试题

关于Java finally的面试题(finally的执行时机,finally和return的先后顺序)

考点:finally语句必然执行 和 return返回值的情况

面试官问题:
1.try-catch-finally 中哪个部分可以省略?

答: catch和finally可以省略其中一个 , catch和finally不能同时省略

注意:格式上允许省略catch块, 但是发生异常时就不会捕获异常了,我们在开发中也不会这样去写代码。

2.什么时候用到finally呢?finally语句在try或catch中的return语句执行之后,还是return返回之前执行呢?

在try{…}catch{…}捕获异常处理语句中:

finally{}必然执行的异常的统一出口,无论是否发生异常,finally必然执行;
除非电脑没电、关机、软件关闭、程序从内存中消失、finally之前出现exit退出,否则finally必然执行。

问题:try-catch-finally 中,如果 catch 中有 return 了,finally 还会执行吗?

答:finally中的代码会执行

详解:执行流程:

  • 1.先计算返回值, 并将返回值存储起来, 等待返回;
  • 2.执行finally代码块;
  • 3.将之前存储的返回值, 返回出去。

需注意:

  • 返回值是在finally运算之前就确定了,并且缓存了,不管finally对该值(非引用数据类型)做任何的改变,返回的值都不会改变
  • finally代码中不建议包含return,因为程序会在上述的流程中提前退出,也就是说返回的值不是try或 catch中的值
  • 如果在try或catch中停止了JVM,则finally不会执行.例如停电…, 或通过如下代码退出 JVM:System.exit(0);

那么执行顺序用代码来解释
看下面这部分代码:

finally举例1:(即使return,在准备返回值与跳出函数之间,仍会执行finally中的语句)
代码:在这里插入图片描述
运行结果:
在这里插入图片描述

finally举例2:(引用数据类型和非引用数据类型的区别)
代码:(引用数据类型)
在这里插入图片描述
运行结果:
在这里插入图片描述
从结果可看出:由于 返回值是引用数据类型
,在return之前准备好p(将引用地址进行备份),但是finally中通过引用数据类型的地址,修改了具体的值,所以还是显示的最终结果会更改属性值为28;

内存分析:
在这里插入图片描述
代码:(非引用数据类型)运行结果:
在这里插入图片描述
内存分析:
在这里插入图片描述

为什么会产生上面这种原因,就是下面要说的关于非引用数据类型(基本数据类型)和引用数据类型的区别:

  • 基本数据类型存在于栈里,那么 return备份的就是数据 。而finally改变的是栈里的数据,但是不会改变备份数据,所以返回值不变。
  • 引用数据类型,数据存在于堆中开辟的空间里,而栈中存储的是堆所对应的空间地址,因此 return备份的是栈中的空间地址 ,但是finally改变的是堆中的数据,所以当return返回地址时,查找到堆中的数据就是被改变了。

那么看完了上面,下面要说的就是fially{…}不执行的条件

finally举例3 :exit()退出[表明终止后面的代码],不执行finally 在这里插入图片描述
这部分代码因为除数不能为0,所以会抛出异常,进入到catch{}里面,在catch里面有一行代码 System.exit(0); 这一行代码的意思就是强制退出程序,因此finally不会执行

  • 退出代码:System.exit( 0)可以输入0.1.2.3 0表示正常退出 剩下是非正常退出。

总结:

  1. finally{…}必然执行异常的统一出口,无论是否发生异常,finally必然执行
  2. 除非电脑没电、关机、软件关闭、程序从内存中消失、finally之前出现exit退出,否则finally必然执行。
  3. 如果是基本数据类型先return 后finally 不会改变值 因为return备份的是值。
  4. 如果是引用数据类型 先return 后finally 会改变值, 因为return备份的是引用类型在堆中的地址,而finally改变的是堆中的值。

猜你喜欢

转载自blog.csdn.net/weixin_46312449/article/details/113011754
今日推荐