eval a string with null_try-with-resources--JAVA成长之路
JDK1.7之后,引入了try-with-resources,使得關閉資源操作無需層層嵌套在finally中,代碼簡潔不少,本質是一個語法糖,能夠使用try-with-resources關閉資源的類,必須實現AutoCloseable接口。
1.7版本之前,傳統的關閉資源操作如下:
public static void main(String[] args){
????FileInputStream?fileInputStream?=?null;????try?{????????fileInputStream?=?new?FileInputStream("file.txt");????????fileInputStream.read();????}?catch?(IOException?e)?{????????e.printStackTrace();????}finally?{????????try?{????????????assert?fileInputStream?!=?null;????????????fileInputStream.close();????????}?catch?(IOException?e)?{????????????e.printStackTrace();????????}????}}可以看到,為了確保資源關閉正常,需要finall中再嵌入finally,try中打開資源越多,finall嵌套越深,可能會導致關閉資源的代碼比業務代碼還要多。
但是使用了try-with-resources語法后,上面的例子可改寫為:
try(FileInputStream?fileInputStream1?=?new?FileInputStream("file.txt")){????fileInputStream1.read();}?catch?(IOException?e)?{????e.printStackTrace();}如何判讀資源是否真的被關閉了呢,我們手寫個Demo:
實現AutoCloseable的資源類
class?MyResource?implements?AutoCloseable{????public?void?open(){????????System.out.println("resource?is?open!");????}????@Override????public?void?close()?throws?Exception?{????????System.out.println("resource?is?close!");????}}調用方:
public?static?void?main(String[]?args){????try(MyResource?myResource?=?new?MyResource()){????????myResource.open();????}?catch?(Exception?e)?{????????e.printStackTrace();????}}輸出如下,可以看到close方法被自動調用了,
resource?is?open!resource?is?close!底層原理是什么呢,看一下編譯后的class文件:
try?{????????MyResource?myResource?=?new?MyResource();????????Throwable?var2?=?null;????????try?{????????????myResource.open();????????}?catch?(Throwable?var12)?{????????????var2?=?var12;????????????throw?var12;????????}?finally?{????????????if?(myResource?!=?null)?{????????????????if?(var2?!=?null)?{????????????????????try?{????????????????????????myResource.close();????????????????????}?catch?(Throwable?var11)?{????????????????????????var2.addSuppressed(var11);????????????????????}????????????????}?else?{????????????????????myResource.close();????????????????}????????????}????????}????}?catch?(Exception?var14)?{????????var14.printStackTrace();????}}很明顯,編譯器生成了finally代碼塊,并在其中調用了close 方法,同1.7之前的關閉資源操作的實現原理是相同的,但是可以看到,這里多調用了一個addSuppressed方法,這么做其實是為了處理異常屏蔽,什么是異常屏蔽,首先,我們先修改一下剛剛的Demo,使資源類在open和close方法中拋出異常,并且使用1.7之前的關閉資源的方法,資源類以及調用方代碼修改如下:
public?void?open()?throws?IOException?{????System.out.println("resource?is?open!");????throw?new?IOException("open()?exception!");}@Overridepublic?void?close()?throws?Exception?{????System.out.println("resource?is?close!");????throw?new?IOException("close()??exception!");}public?static?void?main(String[]?args)?throws?Exception?{????MyResource?myResource?=?null;????try{????????myResource?=?new?MyResource();????????myResource.open();????}finally?{????????try?{????????????myResource.close();????????}?catch?(Exception?e)?{????????????e.printStackTrace();????????}????}}控制臺打印如下:
open方法拋出的異常被自動忽略了,而異常信息丟失將導致程序調試困難,所以try-with-resources語法中加入了addSuppressed處理異常屏蔽,現在修改Demo為使用try-with-resource關閉資源,調用方代碼如下:
public?static?void?main(String[]?args)?throws?Exception?{????try(MyResource?myResource?=?new?MyResource()){????????myResource.open();????}控制臺打印如下
異常信息中多了提示:close方法中拋出的異常被open方法中拋出的異常抑制了。
其他問題:使用try-catch-resources,并不能完全保證資源被關閉,在javaBIO中,使用了大量的裝飾器模式,調用裝飾類的close方法時實際是在調用其中包裹的流的close方法,但是在調用包裹的流的close方法時,裝飾類還做了一些其他的操作,如果這些操作出現異常,將導致包裹流的close方法被跳過,資源沒有被正確關閉,正確的方式是在try中單獨聲明底層資源類以及裝飾類,這樣就可以保證,每個類的close方法都被調用。
總結
以上是生活随笔為你收集整理的eval a string with null_try-with-resources--JAVA成长之路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python数据分析pandas_Pyt
- 下一篇: python多线程处理文件_Python