**
关于Java finally的面试题(finally的执行时机,finally和return的先后顺序)
**
面试官问题:
什么时候用到finally呢?finally语句在try或catch中的return语句执行之后,还是return返回之前执行呢?
在try{}catch{}捕获异常处理语句中:
finally{}必然执行的异常统一处理出口,无论是否发生异常,finally必然执行
除非程序被关闭了 finally才不会执行 电脑关机了 软件在内存里没了 否则finally必然执行
那么执行顺序用代码来解释
看下面这部分代码:
public class Demo1 {
public static void main(String[] args) {
Person p1 = people();
System.out.println(p1.age);
}
public static class Person{
int age;
}
public static Person people(){
Person p = new Person();
try {
p.age = 12;
return p;
}catch (Exception e){
return null;
}finally {
p.age = 20;
}
}
}
这段代码不会产生异常
可能你觉得输出结果是12,但实际上他的返回结果是20
因为finally{},无论程序是否发生异常都必然执行return代表执行完毕,return下面的语句不执行,但在return返回值得时候他有一段备份的时间,而finally就是在备份的这段时间执行的,所以值是20
因此finally是在return后执行的
再看下面这段代码:
public class Demo2 {
public static void main(String[] args) {
int s = people2();
System.out.println(s);
}
public static int people2(){
int i = 12;
try {
i = 15;
return i;
}catch (Exception e){
return 0;
}finally {
i = 20;
}
}
}
你觉得这个结果是20,那么你又错了,这个结果为15.
为什么会产生这种原因,就是下面要说的关于基本数据类型和引用数据类型的区别
基本数据类型存在于栈里,那么return备份的就是数据。而finally改变的是栈里的数据,但是不会改变备份数据,所以返回值不变。
如下图
而引用数据类型,数据存在于堆中开辟的空间里,而栈中存储的是堆的所对应的空间地址,因此return备份的是栈中的空间地址,但是finally改变的是堆中的数据,所以当return返回地址时,查找到堆中的数据就是被改变了
如下图
那么看完了上面,下面要说的就是fially{}不执行的条件
代码如下:
public class demo3 {
public static void main(String[] args) {
people3();
}
public static void people3(){
try {
int i = 10;
int j = 0;
System.out.println(i/j);
}catch (Exception e){
System.out.println("出现了异常程序强制退出!");
System.exit(0);
}finally {
System.out.println("程序结束");
}
}
}
这部分代码因为除数不能为0,所以会抛出异常,进入到catch{}里面,在catch里面有一行代码System.exit(0);
这一行代码的意思就是强制退出程序,因此finally不会执行
结果如下:没有输出程序结束
退出代码:System.exit( 0)可以输入0.1.2.3 0表示正常退出 剩下是非正常退出
总结如下:
1. finally{}必然执行的异常统一处理出口,无论是否发生异常,finally必然执行
2. 除非程序被关闭了 finally才不会执行 电脑关机了 软件在内存里没了 否则finally必然执行
3. 如果是基本数据类型先return 后finally 不会改变值 因为return备份的是值
4. 如果是引用数据类型 先return 后finally 会改变值, 因为return备份的是引用类型在堆中的地址 而finally改变的是堆中的值