2013-12-18 10 views
12

stavo leggendo il try-with-risorsa in JDK7 e mentre pensavo di aggiornare la mia applicazione per l'esecuzione con JDK7 Ho affrontato questo problema ..Eccezione uscendo close() in prova-con-risorsa

Quando si utilizza un BufferedReader, ad esempio, la scrittura genera IOException e la chiusura genera IOException .. nel blocco catch, sono interessato all'IOException lanciata dalla scrittura .. ma non mi interesserebbe molto di quello lanciato dalla chiusura ..

stesso problema con le connessioni al database .. e qualsiasi altra risorsa ..

Come esempio ho creato un resou closeable automatica rce:

public class AutoCloseableExample implements AutoCloseable { 

    public AutoCloseableExample() throws IOException{ 
     throw new IOException(); 
    } 

    @Override 
    public void close() throws IOException { 
     throw new IOException("An Exception During Close"); 
    } 

} 

Ora quando lo si utilizza:

public class AutoCloseTest { 

    public static void main(String[] args) throws Exception { 
     try (AutoCloseableExample example = new AutoCloseableExample()) { 
      System.out.println(example); 

      throw new IOException("An Exception During Read"); 
     } catch (Exception x) { 
      System.out.println(x.getMessage()); 
     } 
    } 

} 

come posso distinguere tra tali eccezioni, senza dover creare wrapper per classi come BufferedReader?

La maggior parte dei casi metto la risorsa chiusa in una prova/cattura all'interno del blocco finally senza preoccuparsi troppo di gestirla.

+0

Dov'è il codice? –

+0

Sto parlando del concetto generale .. comunque .. Aggiungerò uno snippet di codice ora .. –

risposta

10

Consente di considerare la classe:

public class Resource implements AutoCloseable { 

    public Resource() throws Exception { 
     throw new Exception("Exception from constructor"); 
    } 

    public void doSomething() throws Exception { 
     throw new Exception("Exception from method"); 
    } 

    @Override 
    public void close() throws Exception { 
     throw new Exception("Exception from closeable"); 
    } 
} 

e il blocco try-with-risorsa:

try(Resource r = new Resource()) { 
     r.doSomething(); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 

1. Tutte le 3 dichiarazioni tiro abilitati.

Il messaggio "Eccezione da costruttore" verrà stampato e l'eccezione generata dal costruttore sarà soppressa, il che significa che non è possibile accedervi.

2. Il generatore di lancio viene rimosso.

Ora la traccia dello stack stamperà "Eccezione dal metodo" e "Soppresso: eccezione da chiudibile" di seguito. Qui anche tu non puoi catturare l'eccezione soppressa lanciata dal metodo close, ma sarai escluso dall'eccezione soppressa.

3. I rimedi dal costruttore e il metodo vengono rimossi.

Come probabilmente avete già indovinato verrà stampato "Eccezione da chiudibile".

punta Importante: In tutte le situazioni di cui sopra si sono in realtà cattura tutte le eccezioni, non importa dove sono stati gettarono. Quindi se usi il blocco try-with-resource non hai bisogno di avvolgere il blocco con un altro try-catch, è semplicemente inutile.

Speranza che aiuta :)

+0

Grazie per il tuo contributo .. Capisco perfettamente questo .. il problema che sto pensando è come distinguere tra le eccezioni lanciate da metodi come doSomething() e il metodo close() poiché entrambi lanciano lo stesso tipo di eccezione .. il doSomething() merita una presa mentre qualcosa nel flusso si verifica .. mentre l'eccezione generata da close() non è molto di importanza nella maggior parte dei casi e mi fa confondere .. –

+2

Ok, ora capisco qual è il tuo punto. Se si desidera distinguere le eccezioni dal codice, è possibile ottenere il nome del metodo dell'eccezione da 'ex.getStackTrace() [0] .getMethodName()'. Altrimenti potresti semplicemente stampare la traccia dello stack e leggerla. –

0

Io suggerirei di usare una bandiera, come nel seguente esempio:

static String getData() throws IOException { 
    boolean isTryCompleted = false; 
    String theData = null; 
    try (MyResource br = new MyResource();) { 

     theData = br.getData(); 
     isTryCompleted = true; 

    } catch(IOException e) { 
     if (!isTryCompleted) 
      throw e; 
     // else it's a close exception and it can be ignored 
    } 

    return theData; 
} 

fonte: Close resource quietly using try-with-resources