第二章 创建和销毁对象
第八条 避免使用终结方法和清除方法
(完全没接触过,跳过)
第九条 try-with-resources优先于try-finally
Java类库中有很多必须通过调用close()方法来手工关闭的资源(例如InputSteam
和OutputStream
)。
一 关键异常信息被抹除
通常来说,try-finally语句是确保资源关闭的最佳方法,就算是发生异常或者返回也是一样:
//阅读文件的第一行方法
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try{
return br.readLine();
}finally {
br.close();
}
}
这段代码虽然没有问题,但存在不足。
当底层的物理设备异常时,调用readLine()和close()都会抛出异常,这时第二个异常(close抛出的)会完全抹除第一个异常(readLine抛出的)。
这在现实的系统中会导致调试变得非常复杂,因为通常需要看到第一个异常(readLine抛出的)才能诊断出问题何在。
二 使用try-with-resources解决
Java 7引入了try-with-resources语句,使得上面的问题迎刃而解。
要使用这个构造的资源,必须先实现AutoCloseable
接口(BufferedReader的父类Reader实现了Closeable接口,Closeable接口继承自AutoCloseable接口)。
如果编写了一个类,它代表的是必须被关闭的资源,那么这个类也应该实现AutoCloseable
。
//使用try-with-resources语句
static String firstLineOfFile(String path) throws IOException {
try(BufferedReader br = new BufferedReader(new FileReader(path))){
return br.readLine();
}
}
(这个语句的写法,就是把资源的声明放在try后面的括号里,然后不用写close()了。如果有多个资源的声明就用“ ; ”隔开。)
三 优点
使用try-with-resource语句不仅使代码变得简洁易懂,也更容易诊断。
经过改进的firstLineOfFile
方法会禁止close的异常,保留readLine的异常。
这些被禁止的异常并不是简单地被抛弃了,而是会被打印在堆栈轨迹中,并注明它们是被禁止的异常。通过编程调用getSuppressed
方法还可以访问到它们(getSuppressed方法已经添加在Java7的Throwable中了)。
四 总结
在处理必须关闭的资源时,始终要优先考虑用try-with-resource,而不是用try-finally。
这样得到的代码将更加简洁、清晰,产生的异常也更有价值。