java try-with-resources
在本教程中,我们将了解自动关闭资源的 try-with-resources 语句。
在本教程中,我们将了解自动关闭资源的 try-with-resources 语句。
try-with-resources
语句会在语句结束时自动关闭所有资源。能够自动关闭的资源是指实现了 AutoCloseable
接口的类。
try-with-resources
的语法是:
try (resource declaration) {
// use of the resource
} catch (ExceptionType e1) {
// catch block
}
从上面的语法可以看出,我们声明 try-with-resources
语句,
- 在
try
子句中声明和实例化资源。 - 在
catch
指定和处理关闭资源时可能抛出的所有异常。
让我们举一个实现 try-with-resources
语句的例子。
示例 1:try-with-resources
import java.io.*;
public class Main {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
System.out.println("进入了 try-with-resources 代码块");
String line;
while ((line = br.readLine()) != null) {
System.out.println("Line => " + line);
}
} catch (IOException e) {
System.out.println("try 代码块中的异常 =>" + e.getMessage());
}
}
}
如果未找到 test.txt 文件,则输出:
try 代码块中的异常 =>test.txt (系统找不到指定的文件。)
如果找到 test.txt 文件,则输出:
进入了 try-with-resources 代码块
Line => testline
在这个例子中,我们使用了一个 BufferedReader
实例从 test.txt
文件中读取数据。
在 try-with-resources
语句内声明和实例化 BufferedReader
实例对象确保最终被关闭,无论 try
语句是正常完成还是抛出异常。
使用 try-with-resources 的优点
以下是使用 try-with-resources 的优点:
-
不需要
finally
块关闭资源在 Java 7 引入这个特性之前,我们必须使用
finally
块来确保资源关闭以避免资源泄漏。这是一个类似于示例 1 的程序。但是,在这个程序中,我们使用了 finally 块来关闭资源。
示例 2:使用 finally 块关闭资源
import java.io.*; public class Main { public static void main(String[] args) { BufferedReader br = null; String line; try { System.out.println("进入了 try 代码块"); br = new BufferedReader(new FileReader("test.txt")); while ((line = br.readLine()) != null) { System.out.println("Line =>" + line); } } catch (IOException e) { System.out.println("try 代码块中的异常 =>" + e.getMessage()); } finally { System.out.println("进入了 finally 代码块"); try { if (br != null) { br.close(); } } catch (IOException e) { System.out.println("IOException in finally block =>" + e.getMessage()); } } } }
输出
进入了 try 代码块 try 代码块中的异常 =>test.txt (系统找不到指定的文件。) 进入了 finally 代码块
从上面的例子我们可以看出,使用
finally
块来清理资源使得代码更加复杂。注意到
try...catch
块中的finally
块了吗?因为在关闭BufferedReader
实例时也可能发生IOException
异常,因此也需要使用try...catch
处理。try-with-resources
语句自动执行资源的清理工作,不需要我们显式关闭资源。这使代码更具可读性和更易于编写。 -
try-with-resources 多资源
我们可以在
try-with-resources
语句中声明多个资源,用分号;
分隔它们。示例 3:尝试使用多个资源
import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws IOException{ try (Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { while (scanner.hasNext()) { writer.print(scanner.nextLine()); } } } }
如果此程序执行时没有产生任何异常,则
Scanner
对象从testRead.txt
文件中读取一行并将其写入新testWrite.txt
文件中。当声明了多个资源时,
try-with-resources
语句以相反的顺序关闭这些资源。在本例中,先关闭PrintWriter
对象,然后再关闭Scanner
对象。
Java 9 try-with-resources 增强
在 Java 7 中,对 try-with-resources
语句在使用上有限制,资源必须在块本地声明。
try (Scanner scanner = new Scanner(new File("testRead.txt"))) {
// code
}
如果我们在 Java 7 中在 try-with-resources
块外声明资源,它会生成一条错误消息。
Scanner scanner = new Scanner(new File("testRead.txt"));
try (scanner) {
// code
}
为了处理这个错误,Java 9 改进了 try-with-resources
语句,这样即使资源的引用没有在本地声明,也可以使用。上面的代码在 Java 9 能正常执行编译和执行。
总结
以下是关于 try-with-resources
语句的知识要点:
try-with-resources
语句是 Java 7 开始加入的特性。try-with-resources
语句可自动关闭资源。try-with-resources
语句自动关闭的资源类型需要实现AutoCloseable
接口。try-with-resources
可支持声明多个资源。try-with-resources
语句在 Java 9 以后可以使用在语句外声明的资源,Java 9 之前只能使用块内本地声明的资源。try-with-resources
语句让代码更加简洁