2011-10-04 10 views
5

maggior parte del tempo, l'unica cosa che vedo un blocco finally utilizzato per è qualcosa di similePerché devo usare finalmente per chiudere le risorse?

FileInputStream f; 
try{ 
    f= new FileInputStream("sample.txt"); 
    //something that uses f and sometimes throws an exception 
} 
catch(IOException ex){ 
    /* Handle it somehow */ 
} 
finally{ 
    f.close(); 
} 

La mia domanda è, se la portata F termina con il blocco racchiude, perché abbiamo bisogno di chiudere nel finalmente ?

+0

Nel tuo caso, l'ambito di 'f' non termina con il try-block –

+0

@Oli Charlesworth: Questo è chiaramente un esempio leggibile. –

+0

Creazione di un riferimento al file non genera eccezioni (o crea un handle di file), per riferimento futuro. –

risposta

18

Poiché la garbage collection è non la stessa cosa della pulizia delle risorse.

Ad esempio, se si dispone di un oggetto Connessione JDBC che va fuori campo, non viene inviato alcun segnale al server database per indicare che i cursori e le connessioni aperte non sono più necessari. Senza questi messaggi, alla fine esaurirai il numero di cursori e connessioni disponibili.

Uguale agli handle di file e qualsiasi altra risorsa. Ripulisci dopo te stesso.

+2

Sì, certo. Ma perché "finalmente"? –

+5

Poiché è garantito che il codice nel blocco finally venga eseguito, anche se viene generata un'eccezione. – duffymo

+1

@Joe buon esempio. Ma non restituire mai qualcosa in un blocco finale se si dispone di un blocco catch che genera un'eccezione. in tal caso, la tua eccezione non verrà mai lanciata ... imparo questo nel modo più duro ;-) – Cygnusx1

6

Beh, hai dato un cattivo esempio: ho il sospetto che intendessi qualcosa come FileInputStream - ma il motivo fondamentale è che Java non ha una finalizzazione deterministica.

La portata del variabilef termina con il blocco viene dichiarata in (non il blocco try), ma questo non significa che non ci sono necessariamente riferimenti "live" all'oggetto più - e il collettore garbage non finalizzerà l'oggetto e non lo raccoglierà in alcun modo deterministico.

A meno che non si desideri lasciare le risorse in giro per un periodo di tempo arbitrario (e ritardare la garbage collection, poiché i finalizzatori richiedono un giro aggiuntivo di raccolta prima che la memoria sia finalmente rilasciata), è necessario chiudere esplicitamente le risorse.

Fondamentalmente Java fa non supporta RAII nello stesso modo in cui lo fa C++; non dovresti provare a usarlo come se fosse C++.

+0

Modificato per riflettere il tuo suggerimento: stavo appena uscendo con un Closeable dalla memoria, quindi grazie per avermi dato uno che effettivamente si applica : P –

0

La ragione è che Java non garantisce che un oggetto verrà raccolto automaticamente non appena un particolare riferimento ad esso non rientra nell'ambito. Quindi per gli oggetti che fanno riferimento a risorse di sistema limitate, come un descrittore di file, non è sufficiente attendere la garbage collection.

Nota, tuttavia, che java.io.File non è effettivamente un tale oggetto.

1

perché, infine, viene chiamato ogni volta, anche se viene sollevata un'eccezione. il blocco infine ti assicura che il file/connessione sarà chiuso.

0

Abbiamo gestito l'eccezione con try catch finally, infine il blocco ad ogni esecuzione, ma non vi è alcuna garanzia di cattura perché il blocco catch viene eseguito solo se l'eccezione è passata nel parametro corrispondente. Ad esempio, se abbiamo aperto qualsiasi connessione al database, è necessario chiuderlo prima di partire, quindi è necessario implementarlo definitivamente.

Problemi correlati