2013-07-15 17 views
61

Mi aspetto che il lettore e il lettore di file bufferti si chiudano e le risorse rilasciate se l'eccezione viene lanciata.Sto utilizzando correttamente le risorse try-with Java 7

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 
    try (BufferedReader br = new BufferedReader(new FileReader(filePath))) 
    { 
     return read(br); 
    } 
} 

Tuttavia, v'è l'obbligo di avere una clausola catch per la chiusura di successo?

EDIT:

Essenzialmente, è il codice sopra in Java 7 equivalente al di sotto di Java 6:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 

    BufferedReader br = null; 

    try 
    { 
     br = new BufferedReader(new FileReader(filePath)); 

     return read(br); 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 
    finally 
    { 
     try 
     { 
      if (br != null) br.close(); 
     } 
     catch(Exception ex) 
     { 
     } 
    } 

    return null; 
} 
+0

Dopo aver letto di nuovo la tua domanda, non sono sicuro di averlo capito bene. Puoi spiegarlo per favore? – Maroun

+0

Ciao. Ghepardo, sto cercando di capire il ruolo del primo 'catch 'del tuo esempio per Java 6. I.e. 'catch (Exception ex) {throw ex; } '- sta solo rilanciando l'eccezione, non sta facendo nulla, può essere facilmente rimossa senza alcun danno. O mi sta sfuggendo qualcosa? – Sasha

+0

Non c'è niente di sbagliato nella tua sintassi. Se vuoi saperne di più su try-with-resources, consulta questo articolo: [Java try-with-resources] (http://programmergate.com/java-try-resources/) –

risposta

84

È corretto e non c'è alcun requisito per catch clausola. Oracle java 7 doc dice che la risorsa verrà chiusa indipendentemente da se un'eccezione viene effettivamente generata o meno.

È necessario utilizzare una clausola catch solo se si desidera rispondere all'eccezione. La clausola catch verrà eseguita dopo la la risorsa è chiusa.

Ecco un frammento da Oracle's tutorial:

L'esempio seguente legge la prima riga da un file. Utilizza un'istanza di BufferedReader per leggere i dati dal file. BufferedReader è una risorsa che deve essere chiuso dopo che il programma è finito con esso :

static String readFirstLineFromFile(String path) throws IOException { 
    try (BufferedReader br = 
        new BufferedReader(new FileReader(path))) { 
     return br.readLine(); 
    } 
} // In this example, the resource declared in the try-with-resources statement is a BufferedReader. 

... Perché l'istanza BufferedReader viene dichiarato in un comunicato try-con-risorsa, lo farà essere chiuso indipendentemente dal fatto che l'istruzione try venga completata normalmente o in modo brusco (come risultato del metodo BufferedReader.readLine che lancia una IOException).

EDIT

Per quanto riguarda la nuova domanda modificato:

Il codice in Java 6 esegue il catch e poi il blocco finally. Ciò fa sì che le risorse siano ancora potenzialmente aperte nel blocco catch.

In Java 7 sintassi, le risorse sono chiusi prima blocco catch, così risorse sono già chiuse durante l'esecuzione catch blocco. Questo è documentato nel link qui sopra:

In una dichiarazione try-con-risorse, qualsiasi cattura o di blocco finally viene eseguito dopo che le risorse dichiarate sono stati chiusi.

58

L'utilizzo di try-with-resources funzionerà correttamente in questo caso particolare, ma non è del tutto corretto in generale. Non si dovrebbero concatenare risorse del genere perché potrebbero portare a spiacevoli sorprese.Si supponga di avere un buffer di dimensioni variabili:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 
    int sz = /* get buffer size somehow */ 
    try (BufferedReader br = new BufferedReader(new FileReader(filePath), sz)) 
    { 
     return read(br); 
    } 
} 

Assumere qualcosa è andato storto e si è conclusa con sz essere negativo. In questo caso, la risorsa file (creata tramite new FileReader(filePath)) sarà NON chiusa.

per evitare questo problema è necessario specificare ogni risorsa a parte in questo modo:

public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException 
{ 
    int sz = /* get buffer size somehow */ 
    try (FileReader file = new FileReader(filePath); 
     BufferedReader br = new BufferedReader(file, sz)) 
    { 
     return read(br); 
    } 
} 

In questo caso, anche se l'inizializzazione di br non file viene comunque chiusa. Puoi trovare maggiori dettagli here e here.

+0

Sto cercando di capire perché il risorsa creata tramite 'new FileReader (filePath))' non si chiuderà nel caso in cui un 'IllegalArgumentException' venga lanciato quando sz è negativo. Le risorse try-with non chiudono tutte le risorse 'AutoClosable' indipendentemente da eventuali eccezioni generate? –

+2

@PrasoonJoshi No, chiama solo '.close()' per le variabili che sono state dichiarate nell'inizializzatore try-with-resources. Ecco perché separarlo in due dichiarazioni in questo esempio fa il trucco. –

+3

Andrii e @ Mario Hai ragione e torto. Nel primo esempio, FileReader non viene chiuso dalla logica try-with-resource. Ma quando BufferedReader è chiuso, chiuderà anche il FileReader avvolto. Per prova, date un'occhiata all'origine di java.io.BufferedReader.close(). Di conseguenza, si dovrebbe preferire il codice del primo esempio, perché è più conciso. – jschreiner

Problemi correlati