JDK1.7之前
在JDK1.7之前要确保外部资源关闭一般使用finally,如下
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(new File("user.csv"));
System.out.println(inputStream.read());
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
try-with-resource
在JDK1.7及之后对于实现了AutoCloseable接口的对象可以使用try-with-resource语法,该语法会确保外部资源的close方法被调用。如下:
try (FileInputStream inputStream = new FileInputStream(new File("test"))) {
System.out.println(inputStream.read());
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
原理
JDK1.7实现了的一个语法糖,其实对JVM虚拟机而言,它看到的依然是之前的写法,反编译后的结果:
try {
FileInputStream inputStream = new FileInputStream(new File("test"));
Throwable var2 = null;
try {
System.out.println(inputStream.read());
} catch (Throwable var12) {
var2 = var12;
throw var12;
} finally {
if (inputStream != null) {
if (var2 != null) {
try {
inputStream.close();
} catch (Throwable var11) {
var2.addSuppressed(var11);
}
} else {
inputStream.close();
}
}
}
} catch (IOException var14) {
throw new RuntimeException(var14.getMessage(), var14);
}
异常抑制
反编译的代码有一处对异常的特殊处理:
var2.addSuppressed(var11);
这叫异常抑制。当对外部资源进行处理和关闭外部资源时都遇到异常,catch到的将会是对外部资源进行处理时遭遇的异常,关闭资源的异常将被“抑制”(但不是丢弃),通过异常的getSuppressed方法,可以提取出被抑制的异常。