本教程适用于JDK 8。本页中描述的示例和实践不利用后续版本中引入的改进,并且可能使用已不再可用的技术。
请参阅Java语言变化了解Java SE 9及其后续版本中更新的语言特性的概述。
请参阅JDK发行说明了解所有JDK发行版本的新功能、增强功能和已删除或弃用选项的信息。
try
try
资源try
java.lang.AutoCloseable
java.io.Closeable
FileReader
BufferedReader
FileReader
BufferedReader
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
方法的调用顺序与它们的创建顺序相反。
try
java.sql.Statement
java.sql.Statement
try
try
catch
finally
try
catch
finally
try
writeToFileZipFileContents
try
ZipFile
BufferedWriter
try
try
try
try
writeToFileZipFileContents
try
Throwable.getSuppressed
try
AutoCloseableCloseable