Files
effective-Java/ch02创建和销毁对象/09.使用try-with-resources语句替代try-finally语句.md

94 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 使用try-with-resources语句替代try-finally语句
### 示例
**示例代码**[Item09Example01.java](CreatingAndDestroyingObjects/src/main/java/com/jueee/item09/Item09Example01.java)
### 说明
从以往来看try-finally语句是保证资源正确关闭的最佳方式即使是在程序抛出异常或返回的情况下
```java
// try-finally - No longer the best way to close resources!
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}
```
这可能看起来并不坏,但是当添加第二个资源时,情况会变得更糟:
```java
// try-finally is ugly when used with more than one resource!
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
out.close();
}
} finally {
in.close();
}
}
```
即使是用try-finally语句关闭资源的正确代码如前面两个代码示例所示也有一个微妙的缺陷。 try-with-resources块和finally块中的代码都可以抛出异常。 例如,在`firstLineOfFile`方法中,由于底层物理设备发生故障,对`readLine`方法的调用可能会引发异常,并且由于相同的原因,调用`close`方法可能会失败。 在这种情况下,第二个异常完全冲掉了第一个异常。
当Java 7引入了try-with-resources语句时所有这些问题一下子都得到了解决。
要使用这个构造,资源必须实现 `AutoCloseable`接口,该接口由一个返回为`void``close`组成。Java类库和第三方类库中的许多类和接口现在都实现或继承了`AutoCloseable`接口。如果你编写的类表示必须关闭的资源,那么这个类也应该实现`AutoCloseable`接口。
以下是我们的第一个使用try-with-resources的示例
```java
// try-with-resources - the the best way to close resources!
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
return br.readLine();
}
}
```
以下是我们的第二个使用try-with-resources的示例
```java
// try-with-resources on multiple resources - short and sweet
static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
```
不仅 try-with-resources版本比原始版本更精简更好的可读性而且它们提供了更好的诊断。
可以在 try-with-resources语句中添加catch子句就像在常规的try-finally语句中一样。这允许你处理异常而不会在另一层嵌套中污染代码。作为一个稍微有些做作的例子这里有一个版本的`firstLineOfFile`方法,它不会抛出异常,但是如果它不能打开或读取文件,则返回默认值:
```java
// try-with-resources with a catch clause
static String firstLineOfFile(String path, String defaultVal) {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
return defaultVal;
}
}
```
结论明确在处理必须关闭的资源时使用try-with-resources语句替代try-finally语句。 生成的代码更简洁,更清晰,并且生成的异常更有用。 try-with-resources语句在编写必须关闭资源的代码时会更容易也不会出错而使用try-finally语句实际上是不可能的。