1.描述
资源若实现Closeable或者AutoCloseable接口,则可以在try括号里创建,这样,就会自动调用close()方法去自动关闭资源。这就是try-with-resource机制。
2.优点:若是不采用该机制,我们通常需要在finallly代码块中释放资源,为了防止报错,还要加上try-catch,有时候 业务代码 都没有 资源释放需要的代码多。采用try-with-resource机制会使得代码 变得更加简洁;
Closeable继承自AutoCloseable接口,将close函数的Exception异常变为了IOException异常;
3.底层实现:
try-with-resource是一种语法糖机制,是由编译器来最终实现的,通过反编译可以看到,编译器会保证resource的close会被调用到(在try的代码最后、以及catch里面调用了close,从而保证正常执行、以及异常时 都会调用close);
具体的代码,方便自己理解,如下:
import org.junit.jupiter.api.Test;
import java.io.BufferedInputStream;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.IOException;
public class TryWithResourceTest {
/***1.自定义资源 ****************************/
public static class MyCloseResource implements Closeable {
MyCloseResource() {
System.out.println("【Closable】-创建");
}
@Override
public void close() throws IOException {
System.out.println("【Closable】-close");
throw new IOException("【Closable】-关闭报错");
}
}
@Test
public void testClosable() {
try (MyCloseResource r = new MyCloseResource()) {
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 反编译后----------
@Test
public void testClosable_1() {
try {
MyCloseResource r = new MyCloseResource();
r.close();
} catch (IOException var2) {
throw new RuntimeException(var2);
}
}
public static class MyAutoCloseResource implements AutoCloseable {
MyAutoCloseResource() {
System.out.println("【AutoCloseable】-创建");
}
@Override
public void close() throws Exception {
System.out.println("【AutoCloseable】-close");
throw new Exception("【AutoCloseable】-关闭报错");
}
}
@Test
public void testAutoCloseable() {
try (MyAutoCloseResource r = new MyAutoCloseResource()) {
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/****2.单个资源的额情况 *********************/
@Test
public void testReadFile2_1() {
try (FileInputStream fis = new FileInputStream("/Users/data.txt")) {
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void testReadFile2_11() {
try {
FileInputStream fis = new FileInputStream("/Users/data.txt");
// 单个资源,会自动调用close
fis.close();
} catch (IOException var6) {
throw new RuntimeException(var6);
}
}
@Test
public void testReadFile2_2() {
try (FileInputStream fis = new FileInputStream("/Users/data.txt")) {
// 多个一个输出,会多了一个try-catch代码块
System.out.println("");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void testReadFile2_21() {
try {
FileInputStream fis = new FileInputStream("/Users/data.txt");
try {
System.out.println("");
} catch (Throwable var5) {
try {
fis.close();
} catch (Throwable var4) {
var5.addSuppressed(var4);
}
throw var5;
}
fis.close();
} catch (IOException var6) {
throw new RuntimeException(var6);
}
}
/***3.多个复杂资源的情况 ****************************************/
@Test
public void testReadFile1() {
try (FileInputStream fis = new FileInputStream("/Users/data.txt");
BufferedInputStream bis = new BufferedInputStream(fis)) {
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void testReadFile11() {
try {
FileInputStream fis = new FileInputStream("/Users/data.txt");
try {
BufferedInputStream bis = new BufferedInputStream(fis);
// 会自动调用bis.close
bis.close();
} catch (Throwable var5) {
// bis.close异常会调用这里
try {
// 包在try-catch里面,是因为若是有异常,可以追加到原来的异常里面
fis.close();
} catch (Throwable var4) {
var5.addSuppressed(var4);
}
throw var5;
}
// bis.close没有发生异常,会调用这里
fis.close();
} catch (IOException var6) {
throw new RuntimeException(var6);
}
}
}