2010-06-30 14 views
8

Penso ai seguenti esempi; ma non riuscivo a capire quale fosse l'importanza del blocco finale. Puoi dirmi la differenza delle esecuzioni di questi due esempi di codice? Anche un esempio di vita reale può essere utile.Qual è l'essenza del blocco finale in Java?

Esempio 1:

try{ 
     // some code 1 
    }catch(Exception ex){ 
     // print exception 
    }finally{ 
     // some code 2    
    } 

Esempio 2:

try{ 
     // some code 1 
    }catch(Exception ex){ 
     // print exception 
    } 
    // some code 2 
+0

Nota che raramente è utile avere un 'try' dichiarazione sia con un' catch' e "finalmente" se non vuoi il codice disordinato. –

+0

@ Tom perché? servono 2 scopi completamente diversi, il problema è la gestione del fallimento, infine è per la gestione delle risorse. – james

+0

@james Sì, hanno usi completamente diversi, il che significa che il loro ambito dovrebbe essere in genere diverso. –

risposta

17

C'è una grande differenza nei due snippet che hai presentato, ad es. quando il blocco catch genera un'eccezione, il blocco finally viene comunque eseguito dalla relativa semantica.

che è la seguente stampa frammento "Finally!", ma non "What about me???":

try { 
     throw null;  // throws NullPointerException! 
    } catch (Exception e) { 
     int oops = 1/0; // throws ArithmeticException! 
    } finally { 
     System.out.println("Finally!"); // still gets executed! 
    } 
    System.out.println("What about me???"); // doesn't get executed! 

In generale, il finally di un blocco trypraticamente sempre Viene eseguito. Non esiste alcuna garanzia per alcun codice successivo al blocco try.


Ma cosa succede se il mio blocco catch è solo un semplice print dichiarazione?

C'è ancora alcuna garanzia che non sarà throw qualcosa. Qualcosa potrebbe ancora andare storto, ad es. la costruzione per il messaggio dettagliato di eccezione.

Anche se si fa il possibile per garantire che il codice catch sia "sicuro" e il codice che segue l'istruzione try verrà sempre eseguito, la domanda diventa "Perché?". Perché evitare lo finally ma provare così tanto a replicare la sua semantica?

finally la semantica è garantita, senza alcun onere della prova da parte dello scrittore o del lettore del codice. Proprio per questo, è idiomatico utilizzare il blocco finally per inserire il codice "clean-up" obbligatorio. L'utilizzo di finally garantisce la correttezza e migliora sia la leggibilità che la leggibilità.

+0

Hai l'idea. Nel caso in cui ho appena chiamato la funzione di stampa in blocco catch, finalmente non ha importanza ?? – abuzittin

+0

@abuzittin: più della semantica, lo stesso PATTERN è importante. È idiota inserire i codici di pulitura obbligatori in "finalmente". La semantica 'finally' rende l'intento molto più chiaro. Inoltre, una semplice stampa può, in alcune circostanze, generare un'eccezione (ad es. 'IOException', il logger è andato molto forte, la costruzione dei messaggi è andata male, ecc.). – polygenelubricants

+1

Attenzione, potrebbe ancora non riuscire a eseguire se succede qualcosa di catastrofico (ad esempio: l'utente uccide il processo o scollega la macchina), ma per quanto riguarda le eccezioni vai bene. –

2

Si utilizza il blocco finally per la pulizia ed eseguire qualsiasi codice che deve essere eseguito se un'eccezione è stata lanciata (e catturato) o non. Questo include il codice che hai nel blocco catch.

+0

Vuoi dire se ho un codice di blocco catch che può generare un'eccezione? Nel caso in cui ho appena chiamato la funzione di stampa, finalmente non ha importanza ?? – abuzittin

8

Il blocco finally viene eseguito anche se ad es. viene generato un valore Error, che non viene rilevato dal blocco catch nell'esempio. Quindi puoi inserire il codice cleanup nel blocco finally, che dovrebbe essere eseguito sempre, indipendentemente dal risultato delle operazioni nei blocchi try e catch.

Nota che in genere i blocchi catch catturano tipi più specifici di eccezioni, spesso solo le eccezioni controllate, quindi nella maggior parte dei casi la differenza tra i due esempi di codice sopra è molto definita.

Aggiornamento: si può dire che il tuo blocco catch non può mai generare un'eccezione, quindi finally non è necessario. Tuttavia, notare due cose:

  • questo è solo l'corrente stato del codice, e può cambiare in futuro - si può garantire che il futuro programmatore che aggiunge un po 'di codice potenzialmente-eccezione gettare la catch blocco, si ricorderà di inserire il codice cleanup in un blocco finally?
  • try-catch-finally è un idioma di programmazione che rende più semplice per le persone leggere il codice per capire cosa sta succedendo. Se non usi l'idioma comune, rischi di fraintendere, quindi di bug a lungo termine.
+0

Eccezione o errore. Se ripensiamo alla mia domanda con Errore invece di Eccezione, quale sarà la tua risposta? – abuzittin

+0

Grazie per la parte di aggiornamento. – abuzittin

+0

@abuzittin, nel frattempo ho aggiornato il mio post, che credo risponda alla tua domanda. Dovrebbe essere 'Throwable', non' Error'. –

1

è utile quando vogliamo liberare le risorse utilizzate nel blocco try. Quindi l'unico posto in cui eseguirli senza mancare in ogni caso è infine il blocco. Dal momento che se viene lanciata un'eccezione, java non esegue il codice immediatamente successivo. salta direttamente al blocco catch.

0

Nota che si può avere anche provare-finalmente senza un fermo:

try{ 
    // some code 
}finally{ 
    // cleanup code 
} 

Un esempio quindi potrebbe essere un metodo che vuole per propagare le eccezioni al chiamante, ma ancora ha bisogno di codice di pulizia, come il rilascio di una Guarda.

0

Nel caso in cui le istruzioni nel blocco try generino eccezioni non verificate, il blocco verrà infine eseguito consentendo al programmatore di eseguire le azioni pertinenti.

0

Nella realtà, il blocco finally viene utilizzato per chiudere le risorse aperte anche se si verifica un'eccezione. Per esempio, quando si legge (o scrivere) un file, quando si accede a un database, ecc

public void readFile(String fileName) { 
    FileReader fr; 
    BufferedFileReader bfr; 

    try { 
     fr = new FileReader(fileName); 
     bfr = new BufferedFileReader(fr); 
     // ... 
    } catch (IOException ioe) { 
     // ... 
    } finally { 
     // TO ENSURE THAT THE READERS ARE CLOSED IN ALL CASES 
     if (bfr != null) { 
      try { 
       bfr.close(); 
      } catch (IOException ignoredIOE) {} 
     } 
     if (fr != null) { 
      try { 
       fr.close(); 
      } catch (IOException ignoredIOE) {} 
     } 
    } 
} 
Problemi correlati