java8學習第二篇:try-with-resources
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掉。