try-with-resources語句可確保在語句末尾關閉每個資源。 任何實現java.lang.AutoCloseable或java.io.Closeable接口的對象都可以用作資源。
在嘗試使用資源 (在Java 7之前)處理SQL語句或ResultSet或Connection對象或其他IO對象之前,必須顯式關閉資源。 所以一個人會寫類似:
try{//Create a resource- R
} catch(SomeException e){//Handle the exception
} finally{//if resource R is not null thentry{//close the resource}catch(SomeOtherException ex){}
}
我們必須顯式關閉資源,從而添加更多代碼行。 在極少數情況下,開發人員會忘記關閉資源。 因此,為了克服這些問題和其他問題,Java 7中引入了try-with-resources 。
讓我們看一個示例,說明如何在Java 7之前的版本中使用try..catch…。讓我創建2個自定義異常-ExceptionA和ExceptionB。 這些將在整個示例中使用。
public class ExceptionA extends Exception{public ExceptionA(String message){super(message);}
}
public class ExceptionB extends Exception{public ExceptionB(String message){super(message);}
}
讓我們創建一些資源,例如OldResource,它有兩種方法– doSomeWork():完成一些工作,close():完成關閉。 請注意,這描述了通用資源的使用-做一些工作,然后關閉資源。 現在,每個操作doSomeWork和close都會引發異常。
public class OldResource{public void doSomeWork(String work) throws ExceptionA{System.out.println("Doing: "+work);throw new ExceptionA("Exception occured while doing work");}public void close() throws ExceptionB{System.out.println("Closing the resource");throw new ExceptionB("Exception occured while closing");}
}
讓我們在示例程序中使用此資源:
public class OldTry {public static void main(String[] args) {OldResource res = null;try {res = new OldResource();res.doSomeWork("Writing an article");} catch (Exception e) {System.out.println("Exception Message: "+e.getMessage()+" Exception Type: "+e.getClass().getName());} finally{try {res.close();} catch (Exception e) {System.out.println("Exception Message: "+e.getMessage()+" Exception Type: "+e.getClass().getName());}}}
}
輸出:
Doing: Writing an article
Exception Message: Exception occured while doing work Exception Type: javaapplication4.ExceptionA
Closing the resource
Exception Message: Exception occured while closing Exception Type: javaapplication4.ExceptionB
該程序很簡單:創建一個新資源,使用它,然后嘗試關閉它。 可以看看那里多余的代碼行數。
現在,讓我們使用Java 7的try-with-resource結構實現相同的程序。 為此,我們需要一個新資源– NewResource。 在Java 7中,新接口為java.lang.AutoCloseable 。 那些需要關閉的資源將實現此接口。 所有較舊的IO API,套接字API等都實現了Closeable接口-這意味著可以關閉這些資源。 使用Java 7, java.io.Closeable實現AutoCloseable 。 因此,一切正常,而不會破壞任何現有代碼。
下面的NewResource代碼:
public class NewResource implements AutoCloseable{String closingMessage;public NewResource(String closingMessage) {this.closingMessage = closingMessage;}public void doSomeWork(String work) throws ExceptionA{System.out.println(work);throw new ExceptionA("Exception thrown while doing some work");}public void close() throws ExceptionB{System.out.println(closingMessage);throw new ExceptionB("Exception thrown while closing");}public void doSomeWork(NewResource res) throws ExceptionA{res.doSomeWork("Wow res getting res to do work");}
}
現在,使用try-with-resource在示例程序中使用NewResource:
public class TryWithRes {public static void main(String[] args) {try(NewResource res = new NewResource("Res1 closing")){res.doSomeWork("Listening to podcast");} catch(Exception e){System.out.println("Exception: "+e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());}}
}
輸出:
Listening to podcast
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA
上面要注意的一件事是,關閉方法拋出的異常被worker方法拋出的異常所抑制。
因此,您可以立即注意到這兩種實現之間的差異,一種實現最終使用try ... catch ...,另一種使用try-with-resource。 在上面的示例中,僅一個資源被聲明為已使用。 一個人可以在try塊中聲明和使用多個資源,也可以嵌套這些try-with-resources塊。
隨之,在java.lang.Throwable類中添加了一些新方法和構造函數,所有這些方法都與抑制與其他異常一起拋出的異常有關。 最好的例子是-try塊拋出的ExceptionA會被finally(關閉資源時)拋出的ExceptionB抑制,這是Java 7之前的行為。
但是,對于Java 7,拋出的異常會跟蹤它在被捕獲/處理的過程中被抑制的異常。 因此,前面提到的示例可以重新陳述如下。 由close方法拋出的ExceptionB被添加到由try塊拋出的ExceptionA的抑制異常列表中。
讓我用以下示例說明您嵌套的try-with-resources和Suppressed異常。
嵌套的嘗試資源
public class TryWithRes {public static void main(String[] args) {try(NewResource res = new NewResource("Res1 closing");NewResource res2 = new NewResource("Res2 closing")){try(NewResource nestedRes = new NewResource("Nestedres closing")){nestedRes.doSomeWork(res2);}} catch(Exception e){System.out.println("Exception: "+e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());}}
}
上面的輸出將是:
Wow res getting res to do work
Nestedres closing
Res2 closing
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA
注意關閉資源的順序,最新的優先。 還要注意,抑制了每個close()操作引發的異常。
讓我們看看如何檢索被抑制的異常:
禁止的異常
public class TryWithRes {public static void main(String[] args) {try(NewResource res = new NewResource("Res1 closing");NewResource res2 = new NewResource("Res2 closing")){try(NewResource nestedRes = new NewResource("Nestedres closing")){nestedRes.doSomeWork(res2);}} catch(Exception e){System.out.println("Exception: "+e.getMessage()+" Thrown by: "+e.getClass().getSimpleName());if (e.getSuppressed() != null){for (Throwable t : e.getSuppressed()){System.out.println(t.getMessage()+" Class: "+t.getClass().getSimpleName());}}}}
}
上面代碼的輸出:
Wow res getting res to do work
Nestedres closing
Res2 closing
Res1 closing
Exception: Exception thrown while doing some work Thrown by: ExceptionA
Exception thrown while closing Class: ExceptionB
Exception thrown while closing Class: ExceptionB
Exception thrown while closing Class: ExceptionB
getSuppressed()方法用于檢索被拋出的異常阻止的異常。 還向Throwable類添加了新的構造函數,該構造函數可用于啟用或禁用異常抑制。 如果禁用,則不會跟蹤任何抑制的異常。
參考: Java 7項目硬幣: Try -with-resources,以及我們的JCG合作伙伴 Mohamed Sanaulla在Experiences Unlimited Blog 上的示例進行了解釋 。
- 速覽Java 7 MethodHandle及其用法
- JDK中的設計模式
- 了解和擴展Java ClassLoader
- Java內存模型–快速概述和注意事項
翻譯自: https://www.javacodegeeks.com/2011/07/java-7-try-with-resources-explained.html