finally通常发生在异常中的末尾
如下:
try{
// 有可能发生异常的代码段
}catch(异常类型1 对象名1){
// 异常的处理操作
}catch(异常类型2 对象名2){
// 异常的处理操作
} ...
finally{
// 异常的统一出口
}
finally语句将作为异常的统一出口,不管是否产生了异常,最终都要执行此段代码。
疑问:
try-catch-finally 中,如果 try 中 return 了,finally 还会执行吗?
答:finally中的代码会执行 。
详解:
执行流程:
- 先计算返回值, 并将返回值存储起来, 等待返回 ,比如放入
- 再执行finally代码块
- 将之前存储的返回值, 返回出去;
- 举例:比如return a1中,先计算a1,备份到x中等待返回;再执行finally中的a2;最后return x。因为finally的执行并不影响x,所以返回的还是值a1.
需注意:
5. 返回值是在finally运算之前就确定了,并且缓存了,不管finally对该值做任何的改变,返回的值都不会改变 。
6. finally代码中不建议包含return,因为程序会在上述的流程中提前退出,也就是说返回的值不是try或catch中的值。
7. 如果在try或catch中停止了JVM(虚拟机),则finally不会执行.例如停电- -, 或通过如下代码退出 JVM:System.exit(0);``
返回值改变的有趣小案例
案例1:返回值不变
public static void main(String[] args){
System.out.println(A());
}
//方法A
public static int A(){
int age ;
try{
age = 18;
return age;
}catch(Exception e){
return 0;
}finally{
age = 28;
}
}
上述方法在main中调用后,返回值 age = 18;
案例2:返回值改变
public static void main(String[] args){
Person p = B();
System.out.println(p.age);
}
//调用Person
public static Person B(){
Person p = new Person();
try{
p.age = 18;
return p;
}catch(Exception e){
return null;
}finally{
p.age = 28;
}
}
//方法Person
static class Person{
int age;
}
上述方法在main中调用后,返回值 age = 28;
原理解释
在java中,基本数据如 int a ,int a = 18 等都存储在栈中;而类(class)则存储在堆中, 如 Person p 存储在栈中,而 p.age(类中的内容)则存储在堆中。
那么堆和栈如何联系呢?
此时栈相当于指针,存储了堆中的地址,凭借地址找到堆中的内容。
如下两幅图:
总结:所以finally中的备份一直不变,只是当存储的为地址时,所在地址存在的内容改变,则最终返回地址中的值改变。除非你返回的是finally中备份的地址。