本文转自这里。
try-with-resources
也是一种try语句,只不过额外声明了一个或多个必须在程序结束时必须关闭的资源。try-with-resources
确保这些资源在程序结束时被关闭,资源是任何实现了java.lang.AutoCloseable
接口的对象,或者任何实现了java.io.Closeable
接口的对象(因为间接实现了java.lang.AutoCloseable
)。
以下代码读取文件中的第一行,它用BufferedReader
来读文件,BufferedReader
就是程序结束时必须关闭的资源。
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
这个例子中,BufferedReader
就是声明在try-with-resources
中的资源,声明语句包含在圆括号中,紧跟try
关键字。BufferedReader
在java SE 7后实现了java.lang.AutoCloseable
接口,因为在try-with-resources
中被声明了,因此不管br.readLine()
有无抛出IOException
,它都会正常关闭。
在java SE 7之前的版本,可以用finally
达到同样的效果。以下代码使用finally
而不是try-with-resources
:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
但是,在上述例子中,readline()和close()都抛了异常,而外部方法readFirstLineFromFileWithFinallyBlock()
抛的是finally
块的异常,try块的异常被抑制了。相比之下,readFirstLineFromFile
方法,如果try
块和try-with-resources
块都有异常抛出,readFirstLineFromFile
最终抛的是try块的异常,而try-with-resources
的异常被抑制了。Java SE 7之后,可以通过方法获取到被抑制的异常。
try-with-resources
可以定义多个资源:
public static void writeToFileZipFileContents(String zipFileName,
String outputFileName)
throws java.io.IOException {
java.nio.charset.Charset charset =
java.nio.charset.StandardCharsets.US_ASCII;
java.nio.file.Path outputFilePath =
java.nio.file.Paths.get(outputFileName);
// Open zip file and create output file with
// try-with-resources statement
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
// Enumerate each entry
for (java.util.Enumeration entries =
zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName =
((java.util.zip.ZipEntry)entries.nextElement()).getName() +
newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
}
多个资源通过分号分割,它们的close
方法会按照定义顺序的倒序被自动调用。
和普通try
一样,try-with-resources
语句可以有catch
和finally
块,任何catch
和finally
都在try-with-resources
定义的资源关闭后执行。
try-with-resources
语句中,如果try
块抛出了一个异常,try-with-resources
也抛出了异常,那么前者异常将被抛出,后者被抑制。可以通过Throwable.getSuppressed
得到被抑制的异常。