Java try-with-resources 语句
try-with-resources 是 Java 7 引入的一种简洁的资源管理方式,适用于需要在使用后自动关闭的资源(如文件、数据库连接、网络连接等)。
try-with-resources 能够很容易地关闭在 try-catch 语句块中使用的资源,所谓的资源(resource)是指在程序完成后,必须关闭的对象。
try-with-resources 语句确保了每个资源在语句结束时关闭。
所有实现了 java.lang.AutoCloseable 接口(其中,它包括实现了 java.io.Closeable 的所有对象),可以使用作为资源。
优势:
- 简化代码:省去手动关闭资源的代码,逻辑更清晰。
- 减少错误:自动处理资源关闭,避免忘记关闭资源或处理
finally
块中出现的异常。 - 提升性能:减少资源泄露,节约系统资源。
基本语法
try-with-resources 语法如下:
try (ResourceType resource = new ResourceType()) { // 使用资源 } catch (ExceptionType e) { // 处理异常 }
在 try 块中声明的资源会在代码执行完毕后自动关闭,甚至在发生异常时也会安全关闭。
使用 AutoCloseable 接口
为了使资源能够被 try-with-resources 使用,该资源必须实现 AutoCloseable 接口
。AutoCloseable 定义了 close() 方法,系统在 try 块结束后会自动调用这个方法关闭资源。
public class Resource implements AutoCloseable { public void doSomething() { System.out.println("Using resource..."); } @Override public void close() { System.out.println("Closing resource..."); } }
在使用时,只需将资源放在 try 块中:
try (Resource res = new Resource()) { res.doSomething(); } catch (Exception e) { e.printStackTrace(); }
输出:
Using resource... Closing resource...
无论是否发生异常,资源都会在 try 块结束后自动调用 close() 方法。
多个资源管理
try-with-resources 可以同时管理多个资源,只需用分号分隔各资源声明即可:
try (Resource res1 = new Resource(); Resource res2 = new Resource()) { res1.doSomething(); res2.doSomething(); } catch (Exception e) { e.printStackTrace(); }
异常处理
优雅处理异常:当多个资源在 close() 时发生异常,try-with-resources 会将第一个异常抛出,而把其他异常作为 Suppressed Exception 附加。可以通过 Throwable.getSuppressed() 方法获取所有被抑制的异常。
实例
public ResourceWithException() throws Exception {
System.out.println("Creating resource...");
}
public void doSomething() throws Exception {
System.out.println("Doing something with resource...");
throw new Exception("Exception in doSomething");
}
@Override
public void close() throws Exception {
System.out.println("Closing resource...");
throw new Exception("Exception in close");
}
}
try (ResourceWithException res = new ResourceWithException()) {
res.doSomething();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
for (Throwable suppressed : e.getSuppressed()) {
System.out.println("Suppressed exception: " + suppressed);
}
}
输出:
Creating resource... Doing something with resource... Closing resource... Caught exception: Exception in doSomething Suppressed exception: java.lang.Exception: Exception in close
使用场景
try-with-resources
主要用于需要显式关闭的资源管理,常见的场景包括:
- 文件操作:
FileInputStream
、FileOutputStream
、BufferedReader
等。 - 数据库连接:
Connection
、Statement
、ResultSet
等。 - 网络通信:
Socket
、ServerSocket
、HttpURLConnection
等。
例如,使用 try-with-resources 读取文件:
实例
import java.io.FileReader;
import java.io.IOException;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
实例
try-with-resources 声明在 JDK 9 已得到改进。如果你已经有一个资源是 final 或等效于 final 变量,您可以在 try-with-resources 语句中使用该变量,而无需在 try-with-resources 语句中声明一个新变量。
实例
输出结果为:
test
以上实例中我们需要在 try 语句块中声明资源 br1,然后才能使用它。
在 Java 9 中,我们不需要声明资源 br1 就可以使用它,并得到相同的结果。
实例
执行输出结果为:
test
在处理必须关闭的资源时,使用 try-with-resources 语句替 代try-finally 语句。 生成的代码更简洁,更清晰,并且生成的异常更有用。 try-with-resources 语句在编写必须关闭资源的代码时会更容易,也不会出错,而使用 try-finally 语句实际上是不可能的。