本教程适用于JDK 8。本页中描述的示例和实践不利用后续版本中引入的改进,并且可能使用已不再可用的技术。
请参阅Java语言变化了解Java SE 9及其后续版本中更新的语言特性的概述。
请参阅JDK发行说明了解所有JDK发行版本的新功能、增强功能和已删除或弃用选项的信息。
trytry资源tryjava.lang.AutoCloseablejava.io.CloseableFileReaderBufferedReaderFileReaderBufferedReader
static String readFirstLineFromFile(String path) throws IOException {
try (FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr)) {
return br.readLine();
}
}
在这个例子中,try-with-resources语句声明的资源是FileReader和BufferedReader。这些资源的声明语句出现在try关键字之后的括号内。Java SE 7及更高版本中,FileReader和BufferedReader类实现了java.lang.AutoCloseable接口。因为FileReader和BufferedReader实例是在try-with-resource语句中声明的,所以无论try语句是否正常完成或者意外中断(例如BufferedReader.readLine方法抛出IOException),它们都会被关闭。
在Java SE 7之前,可以使用finally块来确保资源在try语句正常或意外完成时都被关闭。以下示例使用finally块而不是try-with-resources语句:
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr);
try {
return br.readLine();
} finally {
br.close();
fr.close();
}
}
然而,这个例子可能存在资源泄漏。一个程序不仅要依赖垃圾回收器(GC)在使用完毕后回收资源的内存,还必须通过调用资源的close方法将资源释放回操作系统。然而,如果一个程序在GC回收资源之前未能做到这一点,那么释放资源所需的信息将丢失。这个资源仍然被操作系统视为正在使用中,造成了资源泄漏。
在这个例子中,如果readLine方法抛出异常,并且在finally块中的br.close()语句也抛出异常,那么FileReader将泄露。因此,使用try-with-resources语句来代替finally块来关闭程序的资源。
如果readLine方法和close方法都抛出异常,那么readFirstLineFromFileWithFinallyBlock方法会抛出finally块中抛出的异常;try块中抛出的异常将被抑制。相反,在readFirstLineFromFile的例子中,如果try块和try-with-resources语句都抛出异常,那么readFirstLineFromFile方法会抛出try块中抛出的异常;try-with-resources块中抛出的异常将被抑制。在Java SE 7及更高版本中,可以检索抑制的异常;有关更多信息,请参见抑制的异常部分。
下面的例子检索封装在zip文件zipFileName中的文件的名称,并创建一个包含这些文件名称的文本文件:
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);
// 使用try-with-resources语句打开zip文件并创建输出文件
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
// 枚举每个条目
for (java.util.Enumeration entries =
zf.entries(); entries.hasMoreElements();) {
// 获取条目名称并将其写入输出文件
String newLine = System.getProperty("line.separator");
String zipEntryName =
((java.util.zip.ZipEntry)entries.nextElement()).getName() +
newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
}
在这个例子中,try-with-resources语句包含两个声明,它们之间用分号分隔:ZipFile和BufferedWriter。当紧跟其后的代码块正常或因异常终止时,将按照相反的顺序自动调用BufferedWriter和ZipFile对象的close方法。请注意,资源的close方法的调用顺序与它们的创建顺序相反。
tryjava.sql.Statementjava.sql.StatementtrytrycatchfinallytrycatchfinallytrywriteToFileZipFileContentstryZipFileBufferedWritertrytrytrytrywriteToFileZipFileContentstryThrowable.getSuppressedtryAutoCloseableCloseable