生活随笔
收集整理的這篇文章主要介紹了
Java7里try-with-resources分析--转
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文地址:http://blog.csdn.net/hengyunabc/article/details/18459463
這個所謂的try-with-resources,是個語法糖。實際上就是自動調用資源的close()函數。和Python里的with語句差不多。
例如:
?
[java]?view plaincopy
static?String?readFirstLineFromFile(String?path)?throws?IOException?{??????try?(BufferedReader?br?=?new?BufferedReader(new?FileReader(path)))?{??????????return?br.readLine();??????}??}??
可以看到try語句多了個括號,而在括號里初始化了一個BufferedReader。
?
這種在try后面加個括號,再初始化對象的語法就叫try-with-resources。
實際上,相當于下面的代碼(其實略有不同,下面會說明):
?
[java]?view plaincopy
static?String?readFirstLineFromFileWithFinallyBlock(String?path)?throws?IOException?{??????BufferedReader?br?=?new?BufferedReader(new?FileReader(path));??????try?{??????????return?br.readLine();??????}?finally?{??????????if?(br?!=?null)?br.close();??????}??}?? ?
很容易可以猜想到,這是編繹器自動在try-with-resources后面增加了判斷對象是否為null,如果不為null,則調用close()函數的的字節碼。
?
只有實現了java.lang.AutoCloseable接口,或者java.io.Closable(實際上繼隨自java.lang.AutoCloseable)接口的對象,才會自動調用其close()函數。
有點不同的是Java.io.Closable要求一實現者保證close函數可以被重復調用。而AutoCloseable的close()函數則不要求是冪等的。具體可以參考Javadoc。
?
下面從編繹器生成的字節碼來分析下,try-with-resources到底是怎樣工作的:
?
[java]?view plaincopy
public?class?TryStudy?implements?AutoCloseable{??????static?void?test()?throws?Exception?{??????????try(TryStudy?tryStudy?=?new?TryStudy()){??????????????System.out.println(tryStudy);??????????}??????}??????@Override??????public?void?close()?throws?Exception?{??????}??}?? TryStudy實現了AutoCloseable接口,下面來看下test函數的字節碼:
?
?
[java]?view plaincopy
static?test()V?throws?java/lang/Exception?????TRYCATCHBLOCK?L0?L1?L2?????TRYCATCHBLOCK?L3?L4?L4????L5????LINENUMBER?21?L5????ACONST_NULL????ASTORE?0????ACONST_NULL????ASTORE?1???L3????NEW?TryStudy????DUP????INVOKESPECIAL?TryStudy.<init>?()V????ASTORE?2???L0????LINENUMBER?22?L0????GETSTATIC?java/lang/System.out?:?Ljava/io/PrintStream;????ALOAD?2????INVOKEVIRTUAL?java/io/PrintStream.println?(Ljava/lang/Object;)V???L1????LINENUMBER?23?L1????ALOAD?2????IFNULL?L6????ALOAD?2????INVOKEVIRTUAL?TryStudy.close?()V????GOTO?L6???L2???FRAME?FULL?[java/lang/Throwable?java/lang/Throwable?TryStudy]?[java/lang/Throwable]????ASTORE?0????ALOAD?2????IFNULL?L7????ALOAD?2????INVOKEVIRTUAL?TryStudy.close?()V???L7???FRAME?CHOP?1????ALOAD?0????ATHROW???L4???FRAME?SAME1?java/lang/Throwable????ASTORE?1????ALOAD?0????IFNONNULL?L8????ALOAD?1????ASTORE?0????GOTO?L9???L8???FRAME?SAME????ALOAD?0????ALOAD?1????IF_ACMPEQ?L9????ALOAD?0????ALOAD?1????INVOKEVIRTUAL?java/lang/Throwable.addSuppressed?(Ljava/lang/Throwable;)V???L9???FRAME?SAME????ALOAD?0????ATHROW???L6????LINENUMBER?24?L6???FRAME?CHOP?2????RETURN????LOCALVARIABLE?tryStudy?LTryStudy;?L0?L7?2????MAXSTACK?=?2????MAXLOCALS?=?3??
從字節碼里可以看出,的確是有判斷tryStudy對象是否為null,如果不是null,則調用close函數進行資源回收。
?
再仔細分析,可以發現有一個Throwable.addSuppressed的調用,那么這個調用是什么呢?
其實,上面的字節碼大概是這個樣子的(當然,不完全是這樣的,因為匯編的各種靈活的跳轉用Java是表達不出來的):
?
[java]?view plaincopy
static?void?test()?throws?Exception?{??????TryStudy?tryStudy?=?null;??????try{??????????tryStudy?=?new?TryStudy();??????????System.out.println(tryStudy);??????}catch(Throwable?suppressedException)?{??????????if?(tryStudy?!=?null)?{??????????????try?{??????????????????tryStudy.close();??????????????}catch(Throwable?e)?{??????????????????e.addSuppressed(suppressedException);??????????????????throw?e;??????????????}??????????}??????????throw?suppressedException;??????}??}??
有點暈是吧,其實很簡單。使用了try-with-resources語句之后,有可能會出現兩個異常,一個是try塊里的異常,一個是調用close函數里拋出的異常。
?
當然,平時我們寫代碼時,沒有關注到。一般都是再拋出close函數里的異常,前面的異常被丟棄了。
如果在調用close函數時出現異常,那么前面的異常就被稱為Suppressed Exceptions,因此Throwable還有個addSuppressed函數可以把它們保存起來,當用戶捕捉到close里拋出的異常時,就可以調用Throwable.getSuppressed函數來取出close之前的異常了。
?
總結:
使用try-with-resources的語法可以實現資源的自動回收處理,大大提高了代碼的便利性,和mutil catch一樣,是個好東東。
用編繹器生成的字節碼的角度來看,try-with-resources語法更加高效點。
java.io.Closable接口要求一實現者保證close函數可以被重復調用,而AutoCloseable的close()函數則不要求是冪等的。
參考:
http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
http://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html
http://docs.oracle.com/javase/7/docs/api/java/io/Closeable.html
轉載于:https://www.cnblogs.com/davidwang456/p/7406692.html
總結
以上是生活随笔為你收集整理的Java7里try-with-resources分析--转的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。