finally语句块的执行条件:
(1)与finally对应的try语句块被执行
(2)try语句块没有执行System.exit, 换句话说是JVM没有退出
一. finally语句的执行发生在控制转义语句执行之前
控制转移语句包含:return, break, continue
static int test(){
int a =10;
try{
System.out.println("try block");
a = a +10;
return a;
}catch (Exception e){
System.out.println("catch block");
a += 20;
}finally {
System.out.println("finally block");
a += 30;
}
return a;
}
运行结果:
try block
finally block
20
二. finally中如果return会覆盖try语句块中返回的结果
static int test1(){
Integer a =10;
try{
System.out.println("try block");
a = a +10;
return a;
}catch (Exception e){
System.out.println("catch block");
a += 20;
}finally {
System.out.println("finally block");
a += 30;
return a;
}
// return a;
}
执行结果:
try block
finally block
50
三. finally中如果不return有可能会覆盖try中的结果
static Person test3(){
Person p = new Person("a");
try {
p.name = "b";
return p;
}catch (Exception e){
}finally {
p.name = "c";
p = new Person("d");
}
return p;
}
运行结果:
c
关于java虚拟机如何编译finally代码块,可以在这篇文章中看到https://www.ibm.com/developerworks/cn/java/j-lo-finally/
大致是说:Java 虚拟机会把 finally 语句块作为 subroutine,我的理解是子程序或者方法,直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine之前,try 或者 catch 语句块会保留其返回值到本地变量表。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。
四. 一旦try中发生了异常会执行catct-finally中的语句,执行结果参照try中没有发生异常的情况
总结:
(1)finally的执行发生在try中的return执行后 返回前
(2)finally语句的执行是否会影响最终返回结果需要参考两个方面
- 2.1 finally中是否有return语句
- 2.2 finally中改变的是基本类型还是引用类型
参考:
https://www.ibm.com/developerworks/cn/java/j-lo-finally/