文档

Java™教程
隐藏目录
try-with-resources语句
路径:基本的Java类
课程:异常
章节:捕获和处理异常

使用try-with-resources语句

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语句声明的资源是FileReaderBufferedReader。这些资源的声明语句出现在try关键字之后的括号内。Java SE 7及更高版本中,FileReaderBufferedReader类实现了java.lang.AutoCloseable接口。因为FileReaderBufferedReader实例是在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语句包含两个声明,它们之间用分号分隔:ZipFileBufferedWriter。当紧跟其后的代码块正常或因异常终止时,将按照相反的顺序自动调用BufferedWriterZipFile对象的close方法。请注意,资源的close方法的调用顺序与它们的创建顺序相反。

tryjava.sql.Statementjava.sql.StatementtrytrycatchfinallytrycatchfinallytrywriteToFileZipFileContentstryZipFileBufferedWritertrytrytrytrywriteToFileZipFileContentstryThrowable.getSuppressedtryAutoCloseableCloseable

上一页: finally 块
下一页:将所有内容放在一起