try-with-resources写法

​ 采用try-with-resources写法,当try中代码执行结束(正常结束/异常结束)之后就会调用try()括号中对象的close()方法来关闭资源,虽然表面上来看try-with-resources写法更加优雅

image-20240628134130016

因为实现了autoCLoseAble接口,再try代码块结束后,connection的close方法会自动调用

// 假设dataSource可用
try{
try(Connection conn = dataSource.getConnection()) {
...
String sql = "select * from ...";
try(PreparedStatement statement = conn.prepareStatement(sql)) {
...
}
}
} catch(...) {
...
} finally {
...
}

在执行完后,conn和其中使用的statement等资源会自动关闭,不需要在finally中手动关闭

jdk9新写法

//jdk9可以直接使用已经存在的变量
Connection conn = dataSource.getConnection();
try(conn) {
...
}

示例代码

@Test
public void test() throws IOException {
String filePath = this.getClass().getResource("test.txt").getPath();

try (FileReader fr = new FileReader(filePath);
BufferedReader br = new BufferedReader(fr)) {
System.out.println(br.readLine());
}
}

​ 如上测试用例中,将 FileReaderBufferedReader 的声明与创建,放在了 try 括号内,这样即可以无需手动进行资源关闭了。这其实是一个语法糖,使用该特性时,编译器会自动为我们添加调用 close 方法关闭资源的代码。将生成的 .class 文件反编译得到

@Test
public void test() throws IOException {
String filePath = this.getClass().getResource("test.txt").getPath();
FileReader fr = new FileReader(filePath);

try {
BufferedReader br = new BufferedReader(fr);

try {
System.out.println(br.readLine());java
} catch (Throwable var8) {
try {
br.close();
} catch (Throwable var7) {
var8.addSuppressed(var7);
}

throw var8;
}

br.close();
} catch (Throwable var9) {
try {
fr.close();
} catch (Throwable var6) {
var9.addSuppressed(var6);
}

throw var9;
}

fr.close();
}

​ 编译器使用传统的 try-finally 写法贴心的为我们添加了资源关闭的代码,而且资源关闭的顺序是:try 括号内先声明的资源后关闭,后声明的资源先关闭。而且关闭资源时,若发生异常,其会将其压制,而抛出 try-with-resources 块内发生的异常。

拓展:自定义 AutoClosable 资源

只要是实现了 AutoClosable 接口的资源,都可以使用try-with-resource特性

static class MyResource implements AutoCloseable {
@Override
public void close() {
System.out.println("my resource closed!");
}

public void doSomething() {
System.out.println("do something");
}
}

@Test
public void myResourceTest() {
try (MyResource myResource = new MyResource()) {
myResource.doSomething();
}
}

由此可得,实现 AutoCloseable 接口,只需要实现 close 方法即可,自定义资源与内置资源在 try-with-resources 特性的使用上并无差别。