2015-09-29 69 views
0

的順序請考慮下面的代碼:的Java:嘗試與 - 資源VS的try-catch-終於即將autoclosing

class Bum implements AutoCloseable{ 

    public void bu() throws Exception{ 
     System.out.println("Bu"); 
     throw new Exception(); 
    } 

    @Override 
    public void close(){ 
     System.out.println("Closed"); 
    } 
} 


public class TestTryWith { 
    private static void tryWith(){ 
     try (Bum bum=new Bum()){ 
      bum.bu(); 
     }catch (Exception ex){ 
      System.out.println("Exception"); 
      //ex.printStackTrace(); 
     } 
    } 

    private static void tryCatchFinally(){ 
     Bum bum=new Bum(); 
     try{ 
      bum.bu(); 
     }catch (Exception ex){ 
      System.out.println("Exception"); 
     }finally{ 
      bum.close(); 
     } 
    } 

    public static void main(String[] args) { 
     tryCatchFinally(); 
     System.out.println("------------"); 
     tryWith(); 
    } 

} 

,輸出是:

Bu 
Exception 
Closed 
------------ 
Bu 
Closed 
Exception 

我讀過try-with-resources被編譯器轉換爲try-catch-finally塊。但是,正如你看到的順序是不同的。當我們使用try-with-resources時,在catch子句之前調用close方法。爲什麼?

回答

4

一如既往,答案在JLS中 - 在這種情況下,section 14.20.3.2。基本上,如果在try-with-resources語句中有catch或finally塊,那麼將它轉換爲一個「正常」try/catch/finally塊,其中包含try-with-resources語句而不是您指定的catch/finally塊 - 但與自動關閉的那個。所以,你的嘗試,與資源片斷有效的是:

try { 
    try (Bum bum = new Bum()) { 
     bum.bu(); 
    } 
} catch (Exception ex){ 
    System.out.println("Exception"); 
    //ex.printStackTrace(); 
} 

這又大致相當於:

try { 
    Bum bum = new Bum(); 
    try { 
     bum.bu(); 
    } finally { 
     // It's more complicated than this... 
     bum.close(); 
    } 
} catch (Exception ex){ 
    System.out.println("Exception"); 
    //ex.printStackTrace(); 
} 

所以是catch塊之前執行的「內部」 finally塊,關閉資源在「外部」try聲明中。

+0

和我的答案一樣,但是你包含了JLS鏈接,所以我刪除了它並且獲得了我的投票。 – Andreas