思考一个问题
Java异常捕获机制try…catch…finally块中的finally语句是否一定会被执行?起码在以下两种情况下是不会被执行的:
1.在try之前就返回了,try没有执行到。
2.try中System.exit(0)来终止JVM。JVM都终止了,自然finally也就不会再执行了
栗证
public class FinallyTest1 {
public static void main(String []args){
System.out.println(test1());
}
private static int test1() {
int b = 20;
try {
System.out.println("try语句块");
return b+=80;
}catch (Exception e){
System.out.println("catch语句块");
}finally {
System.out.println("finally语句块");
if (b>25){
System.out.println("b>25,b="+b);
}
}
return b;
}
}
输出结果如下:
try语句块
finally语句块
b>25,b=100
100
说明return语句已经执行了,然后再去执行finally,等finally执行完后,再返回来return 结果。这里已经得到了验证,可是如果finally中也有return语句,那该咋办呢?
finally块中的return会覆盖try块中的return
public class FinallyTest2 {
public static void main(String []args){
System.out.println(test2());
}
private static int test2() {
int b = 20;
try {
System.out.println("try语句块");
return b+=80;
}catch (Exception e){
System.out.println("catch语句块");
}finally {
System.out.println("finally语句块");
if (b>25){
System.out.println("b>25,b="+b);
}
return 200;
}
}
}
输出结果:
try语句块
finally语句块
b>25,b=100
200
这里finally语句块中有return,就直接return结束了,try语句块中的return根本不会再执行了。
这里再抛出另一个思考:如果finally中没有return,但修改了b,那么try中return的是原始值还是新值?
finally中没有return,原来的返回值变不变说不准
案例1:
public class FinallyTest3 {
public static void main(String []args){
System.out.println(test3());
}
private static int test3() {
int b = 20;
try {
System.out.println("try语句块");
return b+=80;
}catch (Exception e){
System.out.println("catch语句块");
}finally {
System.out.println("finally语句块");
if (b>25){
System.out.println("b>25,b="+b);
}
b=150;
}
return 2000;
}
}
输出结果:
try语句块
finally语句块
b>25,b=100
100
案例2:
public class FinallyTest4 {
public static void main(String []args){
System.out.println(getMap().get("key").toString());
}
public static Map<String,String> getMap(){
HashMap<String, String> map = new HashMap<>();
map.put("key","init");
try {
map.put("key","try");
return map;
}catch (Exception e){
map.put("key","catch");
}finally {
map.put("key","finally");
map=null;
}
return map;
}
}
输出结果:
finally
案例1中finally的“干扰”没有起作用,案例2中finally的map.put(“key”,“finally”);起作用了,但是map=null并没起到作用。这里涉及到的就是java到底是传值还是传址了。简单来讲,java只有传值,没有传址,所以map=null;没有起作用。
try块中的return在异常情况下不会执行
public class FinallyTest5 {
public static void main(String []args){
System.out.println(test5());
}
private static int test5() {
int b = 20;
try {
System.out.println("try语句块");
b=b/0;
return b+=80;
}catch (Exception e){
b+=15;
System.out.println("catch语句块");
}finally {
System.out.println("finally语句块");
if (b>25){
System.out.println("b>25,b="+b);
}
b+=50;
}
return b;
}
}
输出结果:
try语句块
catch语句块
finally语句块
b>25,b=35
85
这里try中发生了异常,try中没有return而是被catch,最后到了finally执行了了finally块中的命令
异常发生,catch中的return执行情况和未发生异常的try中return执行情况一样
public class FinallyTest6 {
public static void main(String []args){
System.out.println(test6());
}
private static int test6() {
int b = 20;
try {
System.out.println("try语句块");
b=b/0;
return b+=80;
}catch (Exception e){
System.out.println("catch语句块");
return b+=15;
}finally {
System.out.println("finally语句块");
if (b>25){
System.out.println("b>25,b="+b);
}
b+=50;
}
}
}
输出结果:
try语句块
catch语句块
finally语句块
b>25,b=35
35
异常发生后,catch中的return语句先执行,确定返回值后再去执行finally,然后再返回catch中的return,finally中对b的改变不造成影响。
总结
finally块中的语句,在try或catch中的return语句执行之后、返回之前执行。而且finally语句中的“干扰”可能或不可能影响try、catch中return已经确定的返回值。若finally中也有return则覆盖try、catch中的return语句直接返回。