功能概述
- 在Java的异常处理中,finally语句块无论try语句中是否抛出异常,都能正常执行finally语句块中的内容。主要用于回收在try语句块中打开的资源,比如数据库连接,文件等。
功能实践
场景1:正常执行顺序
用例代码
@Test
public void test_finally_order() {
try {
System.out.println("before statement");
throw new NullPointerException();
} catch (Exception e) {
System.out.println("happen error");
} finally {
System.out.println("finally statement");
}
System.out.println("after statement");
}
运行结果
before statement
happen error
finally statement
after statement
结果分析
- finally块中定义的代码,总是在try和任何catch 块之后、方法完成之前运行。
场景2:与return的顺序
用例代码
@Test
public void test_finally_order_v2() {
System.out.println(sayHello());
}
private String sayHello() {
try {
return "hello";
} finally {
System.out.println("finally statement");
}
}
运行结果
finally statement
hello
结果分析
- 因为finally在try语句块后、方法完成前执行。因为遇到return,方法会结束。所以在return前,就会执行finally
场景3:finally不执行的情况
用例代码
@Test
public void test_finally_no_execution_v1() { //调用System.exit
try {
System.out.println("try statement");
System.exit(1);
} finally {
System.out.println("finally statement");
}
}
运行结果
try statement
结果分析
- 调用System.exit后,就会中断了程序,所以就不会执行后面的finally内容了
- 注明:还有其它不执行finally的场景,如
- 调用Runtime#halt函数
- try代码块中无限循环
- 注明:还有其它不执行finally的场景,如
场景4:陷阱之return覆盖
用例代码
@Test
public void test_finally_trap() {
System.out.println(sayHello());
}
private String sayHello() {
try {
return "from try";
} finally {
return "from finally";
}
}
运行结果
from finally
结果分析
- 如果finally中存在return语句,则try和catch代码块中的返回语句就会被忽略
场景5:陷阱之异常被忽略
用例代码
@Test
public void test_finally_trap() {
System.out.println(sayHello());
/**
* 输出结果:
* try statement
* finally statement
*
* 结果分析:
* finally中含有return语句,也没有通过catch语句捕获异常,所以异常被忽视了
*/
}
private String sayHello() {
try {
throw new RuntimeException();
} finally {
return "from finally";
}
}
运行结果
from finally
结果分析
- finally中只包含return语句,也没有通过catch语句捕获异常,所以异常被忽视了
功能总结
-
正常情况下,try语句中不管是否抛出异常,finally都会被执行,且执行顺序为try/catch语句之后,方法return之前。
-
在执行一些操作,如System.exit系统退出等,就不会执行finally语句了。
-
使用finally时,要注意一些陷阱,避免出现非预期的结果,比如return语句覆盖、异常被忽略等场景。