关于异常finally的问题
1、finally的执行情况
finally块的内容必定会执行,但如若软件关闭、停电等硬件情况,finally块的内容无法执行。
public class Demo5 {
public static void main(String[] args) {
haha();
}
public static void haha(){
try{
System.out.println("1");
System.out.println("2");
System.out.println("3");
System.out.println("4");
return;
}catch(Exception e){
}finally {
System.out.println("锄禾日当午,汗滴禾下土");
}
}
}
输出:
1
2
3
4
锄禾日当午,汗滴禾下土
finally不执行
public class Demo {
public static void main(String[] args) {
haha();
}
public static void haha(){
try{
int a = 10;
int b = 0;
System.out.println(a/b);
}catch(Exception e){
//退出JVM
System.out.println("出现了异常");
System.exit(0);
}finally {
System.out.println("锄禾日当午,汗滴禾下土");
}
}
}
输出:
出现了异常
由于程序执行
System.exit(0)
退出了JVM,因此finally语句块不执行。
2、引用类型数据和基本数据类型
引用数据类型
public class Demo {
public static void main(String[] args) {
Person p = haha();
System.out.println(p.age);
}
public static Person haha(){
Person p = new Person();
try{
p.age = 18;
return p;
}catch(Exception e){
return null;
}finally {
p.age = 28;
}
}
static class Person{
int age;
}
}
输出:
28
由于
Person p = new Person();
在堆内存中开辟空间,而在栈中保存的是该空间的内存地址,return p
进行备份时,备份的是该内存地址。而当finally块中修改了堆内存中的数值时,备份的内存地址是不变的,因此,输出打印的是28
.
基本数据类型
public class Demo {
public static void main(String[] args) {
int a = haha();
System.out.println(a);
}
public static int haha(){
int a = 10;
try{
return a;
}catch(Exception e){
return 0;
}finally {
a = 20;
}
}
//静态内部类
static class Person{
int age;
}
}
输出:
10
基本数据类型,
int a = 10;
在栈中保存的就是数值10
,当return a;
时,备份的就是数值10,而当finally
块中修改a=20
时,备份的仍然是数值10
,因此最后输出的值为10
finally执行流程:
- 先计算返回值, 并将返回值存储起来, 等待返回
- 执行finally代码块
- 将之前存储的返回值, 返回出去;
需注意:
- 返回值是在finally运算之前就确定了,并且缓存了,不管finally对该值做任何的改变,返回的值都不会改变
- finally代码中不建议包含
return
,因为程序会在上述的流程中提前退出,也就是说返回的值不是try
或catch
中的值- 如果在try或catch中停止了JVM,则finally不会执行.例如停电- -, 或通过如下代码退出JVM:
System.exit(0);