在考虑所有可能失败的方法时,找出放置所有 try-catch-finally 块的位置变得令人生畏。确保没有任何故障路径,使系统远离不稳定状态
1、解决两个问题
1.需要资源清理
2.需要在特定的时刻进行资源清理,比如你离开作用域的时候(在通常情况下意味着通过异常进行清理)
- 一个常见的例子是 java.io.FileInputStream (将会在 附录:I/O 流 中提到)。要正确使用它,你必须编写一些棘手的样板代码:
import java.io.*;
public class MessyExceptions {
public static void main(String[] args) {
InputStream in = null;
try {
in = new FileInputStream(
new File("MessyExceptions.java"));
int contents = in.read();
// 内容
} catch(IOException e) {
// 处理错误
} finally {
if(in != null) {
try {
in.close();
} catch(IOException e) {
// 处理close异常
}
}
}
}
}
当 finally 子句有自己的 try 块时,感觉事情变得过于复杂。
幸运的是,Java 7 引入了 try-with-resources 语法,它可以非常清楚地简化上面的代码:
// exceptions/TryWithResources.java
import java.io.*;
public class TryWithResources {
public static void main(String[] args) {
try(
InputStream in = new FileInputStream(
new File("TryWithResources.java"))
) {
int contents = in.read();
// 内容
} catch(IOException e) {
// 处理错误
}
}
}
在 Java 7 之前,try 后面总是跟着一个 {,但是现在可以跟一个带括号的定义 ——这里是我们创建的 FileInputStream 对象。括号内的部分称为资源规范头(resource specification header)。现在 in 在整个 try 块的其余部分都是可用的。更重要的是,无论你如何退出 try 块(正常或通过异常),和以前的 finally 子句等价的代码都会被执行,并且不用编写那些杂乱而棘手的代码。这是一项重要的改进。
它是如何工作的? try-with-resources 定义子句中创建的对象(在括号内)必须实现 java.lang.AutoCloseable 接口,这个接口只有一个方法:close()。当在 Java 7 中引入 AutoCloseable 时,许多接口和类被修改以实现它;查看 Javadocs 中的 AutoCloseable,可以找到所有实现该接口的类列表,其中包括 Stream 对象:
// exceptions/StreamsAreAutoCloseable.java
import java.io.*;
import java.nio.file.*;
import java.util.stream.*;
public class StreamsAreAutoCloseable {
public static void
main(String[] args) throws IOException{
try(
Stream<String> in = Files.lines(
Paths.get("StreamsAreAutoCloseable.java"));
PrintWriter outfile = new PrintWriter(
"Results.txt"); // [1]
) {
in.skip(5)
.limit(1)
.map(String::toLowerCase)
.forEachOrdered(outfile::println);
} // [2]
}
}