Java8里的一个新语法特性:try-with-resources。
这个语法特性其实从java7里就有了,不过java8的sample里依然有这个。
try-with-resources的特性就是,在try( ...)里声明的资源,会在try-catch代码块结束后自动关闭掉。
废话不说,先上代码后分析。
-
public class AutoCloseTest {
-
public static void main(String[] args) {
-
testNormalOutput(args[0]);
-
testAutoCloseWithTryCatch(args[1]);
-
}
-
private static void testNormalOutput(String filepath){
-
OutputStream global_out = null;
-
BufferedWriter writer ;
-
try {
-
OutputStream out = out = new FileOutputStream(filepath);
-
global_out = out;
-
out.write((filepath + "inside try catch block").getBytes());
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
try{
-
if(global_out!=null){
-
global_out.write(" \t\r outside try catch block".getBytes());
-
global_out.close();
-
}
-
} catch (Exception e){
-
e.printStackTrace();
-
}
-
}
-
private static void testAutoCloseWithTryCatch(String filepath){
-
OutputStream global_out = null;
-
try(OutputStream out = new FileOutputStream(filepath);) {
-
global_out = out;
-
out.write((filepath+"inside try catch block").getBytes());
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
try{
-
if(global_out!=null){
-
global_out.write(" \t\r outside try catch block".getBytes());
-
global_out.close();
-
}
-
} catch (Exception e){
-
e.printStackTrace();
-
}
-
}
-
}
运行
java AutoCloseTest d:/a.txt d:/b.txt
然后发现
a.txt里的内容是
d:/a.txt inside try catch block outside try catch block
b.txt里的内容是
d:/b.txt inside try catch block
没错,b.txt的后半段代码没有执行
同时控制台还打印出
-
java.io.IOException: Stream Closed
-
at java.io.FileOutputStream.writeBytes(Native Method)
-
at java.io.FileOutputStream.write(FileOutputStream.java:294)
-
at trywithresources.AutoCloseTest.testAutoCloseWithTryCatch(AutoCloseTest.java:46)
-
at trywithresources.AutoCloseTest.main(AutoCloseTest.java:11)
-
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:483)
-
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
这是因为在testAutoCloseWithTryCatch方法里,global_out所指向的out对象已经在第一次try-catch之后被关闭了
在第二次对这个已经关闭的流里输出内容时,就会报Stream Closed错误。
--------------------*************************-----------------------********************
那么try-with-resources是如何工作的呢?它和finally的工作谁在前呢?我们可以做一个小测试
-
private static void testAutoClose() {
-
AutoCloseable global_obj1 = null;
-
AutoCloseable global_obj2 = null;
-
try(AutoCloseable obj1 = new AutoClosedImpl("obj1");
-
AutoCloseable obj2 = new AutoClosedImpl("obj2");){
-
global_obj1= obj1;
-
int i = 1/0;
-
global_obj2= obj2;
-
} catch (Exception e) {
-
e.printStackTrace();
-
}finally{
-
try{
-
System.out.println("before finally close");
-
if(global_obj1!=null){
-
global_obj1.close();
-
}
-
if(global_obj2!=null){
-
global_obj2.close();
-
}
-
System.out.println("after finally close");
-
} catch(Exception e){
-
e.printStackTrace();
-
}
-
}
-
}
-
private static class AutoClosedImpl implements AutoCloseable{
-
private String name;
-
public AutoClosedImpl(String name){
-
this.name = name;
-
}
-
@Override
-
public void close() throws Exception {
-
System.out.println(name+" closing");
-
}
-
}
执行testAutoClose()方法,会打印出如下结果
-
obj2 closing
-
obj1 closing
-
before finally close
-
obj1 closing
-
after finally close
-
java.lang.ArithmeticException: / by zero
-
at trywithresources.AutoCloseTest.testAutoClose(AutoCloseTest.java:60)
-
at trywithresources.AutoCloseTest.main(AutoCloseTest.java:12)
-
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:483)
-
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
从上述代码我们可以观测四件事
1. 凡是实现了AutoCloseable接口的类,在try()里声明该类实例的时候,在try结束后,close方法都会被调用
2. try结束后自动调用的close方法,这个动作会早于finally里调用的方法。
3. 不管是否出现异常(int i=1/0会抛出异常),try()里的实例都会被调用close方法
4. 越晚声明的对象,会越早被close掉。