一、finally用法
1.语法
完全体的异常捕获处理机制包括try...catch...finally三个模块,语法结构如下:
try{
代码
...
}catch(Exception e){
异常处理代码
...
}finally{
代码
...
}
2.特点
finally在使用时有以下特点。
a.在异常处理时,无论是否发生异常或try/catch中出现return语句,finally中的语句都会被执行
b.finally必须使用在所有catch的最后位置,常用来处理一些后续的工作,如释放资源
二、finally的必要性
考虑一种情况,读取一个文件,并将内容输出到另一个文件中。
FileInputStream in = new FileInputStream(new File("九阴真经.txt"));
FileOutputStream out = new FileOutputStream(new File("九阳真经.txt"));
while((length = in.read(buf)) != -1){
out.write(buf);
}
in.close();
out.close();
正常情况下,读取完文件并输出后,需要关闭文件流。上述代码看似使用完后,已经关闭了资源,但是如果在关闭资源前发生异常。那么文件资源就一直被占用,将造成资源浪费,严重的话可能导致内存溢出等异常。因此就需要一种方法,使得程序在异常和正常时都能释放所占有的资源。这就是finally的价值所在。
三、try、catch、finally中的return执行顺序(经典面试问题)
在探讨异常处理语句try...catch...finally中的代码执行顺序之前,首先记住一条规则:
根据JVM规范,try/catch、finally的return返回值会暂存在一个局部变量中。
1.try、catch中没有return语句
当try和catch中都没有return语句时,执行顺序依次为:
(1)try语句块开始 ——>(2) 语句块异常处 ——>(3) catch语句块 ——> (4) finally语句块
2.try、catch中有return语句,finally中没有return。
四、示例程序
1 public class Test {
2 public static void main(String[] args) {
3 System.out.println(test1());
4 }
5 public static String test1() {
6 try {
7 System.out.println("try block");
8 int a = 5/0;
9 return "try";
10 } catch(Exception e){
11 System.out.println("catch block");
12 return test2();
13 }finally {
14 System.out.println("finally block");
15 return "finally";
16 }
17 }
18 public static String test2() {
19 System.out.println("return statement");
20 return "after return";
21 }
22 }
上述代码的结果为:
try block
catch block
return statement
finally block
finally
分析:
程序执行try中代码并输出"try block",直到行8处发生异常并被捕获;接着执行catch语句块,输出“catch block”,在行12处return进入test2()方法;执行test()输出“return statement”;在20处return结束test2方法并将"after return"返回到12处,catch块结束,return的值为"after return"暂存起来。接着执行finally块,输出"finally block",到15行处return返回值被覆盖为"finally";最后返回到main方法的3行处,输出return结果"finally"。