JDK1.7之后有了try-with-resource处理机制。首先被自动关闭的资源需要实现Closeable或者AutoCloseable接口,因为只有实现了这两个接口才可以自动调用close()方法去自动关闭资源。写法为try(){}catch(){},将要关闭的外部资源在try()中创建,catch()捕获处理异常。其实try-with-resource机制是一种语法糖,其底层实现原理仍然是try{}catch(){}finally{}写法,不过在catch(){}代码块中有一个addSuppressed()方法,即异常抑制方法。如果业务处理和关闭连接都出现了异常,业务处理的异常会抑制关闭连接的异常,只抛出处理中的异常,仍然可以通过getSuppressed()方法获得关闭连接的异常。
以下为try-catch-finally和try-with-resource使用上的对比:
try-catch-finally:
private static void test()throws Exception{
Connection conn = null;
try{
conn = new Connection();
conn.sendData();
} finally{
if(conn !=null) {
try {
conn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行异常结果打印如下:
java.lang.Exception: close
at cn.wangjy.study.trywithresources.Connection.close(Connection.java:18)
at cn.wangjy.study.trywithresources.TryWithResource.test(TryWithResource.java:84)
at cn.wangjy.study.trywithresources.TryWithResource.main(TryWithResource.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
try-with-resource:
public static void main(String[] args) {
try(Connection conn =new Connection()) {
conn.sendData();
}catch(Exception e) {
e.printStackTrace();
}
}
运行异常结果打印如下:
java.lang.Exception: send data
at cn.wangjy.study.trywithresources.Connection.sendData(Connection.java:13)
at cn.wangjy.study.trywithresources.TryWithResource.main(TryWithResource.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Suppressed: java.lang.Exception: close
at cn.wangjy.study.trywithresources.Connection.close(Connection.java:18)
at cn.wangjy.study.trywithresources.TryWithResource.main(TryWithResource.java:72)
... 5 more
可以看到,代码编写也十分简洁。虽然我们没有用finally的代码块写明close(),但是程序仍然会自动执行close()方法,并且异常信息也没有丢失。信息中多了一个Suppressed的提示,附带上close的异常。这个异常其实由两个异常组成, 执行close()的异常是被Suppressed的异常。
try-with-resource也支持多个流关闭 ,资源关闭会按声明时的相反顺序被执行。
public static void main(String[] args) {
try (FileInputStream fin = new FileInputStream(new File("input.txt"));
FileOutputStream fout = new FileOutputStream(new File("out.txt"));
GZIPOutputStream out = new GZIPOutputStream(fout)) {
byte[] buffer = new byte[4096];
int read;
while ((read = fin.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
}
}