JDK7引入了try-with-resources的语法,可以自动关闭在try括号内打开的实现Closeable或者AutoCloseable接口的资源。其实try-with-resource机制是一种语法糖,其底层实现原理仍然是try{}catch(){}finally{}写法,执行顺序是:try块->自动关闭->catch块->finally块,其中自动关闭最先关闭最后打开的资源,逐个资源关闭,最先打开的资源最后关闭,先关闭的资源抛出的异常,会被后关闭的资源抛出的异常抑制(Suppressed),最后只抛出最后一个异常可以被catch捕获,因为try块中的业务逻辑先执行,资源关闭后执行,所以资源关闭抛出的异常也会抑制try块中业务逻辑的异常,可以通过getSuppressed()方法获得全部关闭连接的异常。
需要注意的是,如果资源未在try中定义,如下例所示的GZIPOutputStream构造方法内实例化FileOutputStream,则不会被自动关闭。
try (FileInputStream fin = new FileInputStream(new File("in.txt"));
GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(new File("out.txt")))) {
//dosomething
} catch(IOException e) {
//log error
}
JDK9中对try-with-resources语法进行了优化,如果已经有一个资源是final或等效于final的变量,可以在try-with-resources 语句中使用该变量,而无需在try-with-resources语句中声明一个新变量。上例可以改写成如下形式,并解决FileOutputStream无法自动关闭问题:
final FileInputStream fin = new FileInputStream(new File("in.txt");
FileOutputStream fout = new FileOutputStream(new File("out.txt"));
GZIPOutputStream out = new GZIPOutputStream(fout);
try (fin;fout;out) {
//dosomething
} catch(IOException e) {
//log error
}