2016-01-15 10 views
6

Nel seguente blocco di codice:Cosa viene catturato esattamente in un'istruzione estesa di try-with-resources?

try (/* resources declaration */) { 
    // some dangerous code 
} catch (Exception e) { 
    // error handling and reporting 
} 

cosa sarebbe successo se sia il codice all'interno del blocco e l'tryclose() dichiarazione automatica gettato eccezioni? Quale verrebbe catturato nel blocco catch? Entrambi? Solo uno di loro? Se sì, quale?

Inoltre, cosa succede se lo try ha esito positivo ma lo close non lo è? Verrà inserito il blocco di cattura?

risposta

6

Citando dalla sezione JLS 14.20.3.1:

In una dichiarazione di base try-con-le risorse che gestisce una singola risorsa:

  • Se l'inizializzazione della risorsa completa bruscamente a causa di un throw di un valore V, quindi l'istruzione try-with-resources viene completata improvvisamente a causa di un valore throw del valore V.
  • Se l'inizializzazione della risorsa completa normalmente, e il blocco try completa bruscamente a causa di un throw di un valore V, quindi:

    • Se la chiusura automatica della risorsa completa normalmente, allora la prova -with-resource statement completa bruscamente a causa di un throw del valore V.

    • Se la chiusura automatica della risorsa completa bruscamente a causa di un throw di un valore V2, allora l'istruzione try-with-risorse completa bruscamente a causa di un throw valore V con V2 aggiunti all'elenco delle eccezioni soppressa di V .

  • Se l'inizializzazione della risorsa completa normalmente, e il blocco try completa normalmente, e la chiusura automatica della risorsa completa bruscamente a causa di un lancio di un valore V, allora l'istruzione try-with-risorse completa bruscamente a causa di un throw del valore V.

Ciò significa che se sia il codice all'interno del try blocco e il close() dichiarazione automatica un'eccezione, la parte catch gestirà l'eccezione generata dal blocco try, con l'eccezione generata dal close() nel suppressed exceptions .

Inoltre, ciò significa che se il blocco try ha successo ma l'automatico close() fallisce, il catch sarà davanzale essere eseguito e l'eccezione catched sarà l'eccezione generata da close().


Ecco un test per verificare questo comportamento:

public class Main { 
    public static void main(String[] args) throws Exception { 
     // try block fails and close() fails 
     try (T t = new T()) { 
      throw new Exception("thrown by try part"); 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
      System.out.println(e.getSuppressed()[0].getMessage()); 
     } 

     // try block is successful but close() fails 
     try (T t = new T()) { 
      // 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
     } 
    } 
} 

class T implements AutoCloseable { 
    @Override 
    public void close() throws Exception { 
     throw new Exception("thrown by close"); 
    } 
} 

Questo codice stamperà

thrown by try part 
thrown by close 
thrown by close 

il che significa che l'eccezione catturato è stato l'eccezione generata dalla parte try del codice per la prima parte. Per la seconda parte, l'eccezione rilevata era effettivamente l'eccezione generata da close().

-1

L'eccezione generata all'interno del blocco try viene generata all'esterno.

Mentre con try-catch-finally l'eccezione generata dal blocco finally viene propagata allo stack di chiamate.

InputStream input = null; 

    try { 
     input = new FileInputStream("file.txt"); 

     int data = input.read(); 
     while(data != -1){ 
      System.out.print((char) data); 
      data = input.read(); 
     } 
    } finally { 
     if(input != null){ 
      input.close(); 
     } 
    } 

In questo caso, se si verifica un'eccezione sia nel blocco try e il blocco finally (quando l'InputStream è chiuso), il l'ultimo viene lanciata, anche se l'eccezione generata dal blocco try probabilmente essere più rilevanti da propagare.

try(FileInputStream input = new FileInputStream("file.txt")) { 

     int data = input.read(); 
     while(data != -1){ 
      System.out.print((char) data); 
      data = input.read(); 
     } 
    } 

Mentre in questo caso, se si verifica un'eccezione sia nel blocco try e il blocco finally, il primo si propaga

+0

C'è un'istruzione catch che gestirà le eccezioni generate dal 'try'. Non so come queste eccezioni saranno gettate nel mondo esterno. –

+0

se la risorsa chiudibile genera un'eccezione quando è chiusa, l'eccezione che si è verificata nel blocco try è più rilevante, quindi è propagata – Chris

+0

Per favore leggi di nuovo la domanda, guarda che OP sta chiaramente affermando che ** c'è un'istruzione 'catch' in uso ** –