Differenza tra try-infine e try-catch


91

Qual è la differenza tra

try {
    fooBar();
} finally {
    barFoo();
}

e

try {
  fooBar();
} catch(Throwable throwable) {
    barFoo(throwable); // Does something with throwable, logs it, or handles it.
}

Mi piace di più la seconda versione perché mi dà accesso a Throwable. C'è qualche differenza logica o una convenzione preferita tra le due varianti?

Inoltre, c'è un modo per accedere all'eccezione dalla clausola finalmente?

Risposte:


121

Queste sono due cose diverse:

  • Il blocco catch viene eseguito solo se viene generata un'eccezione nel blocco try.
  • Il blocco finalmente viene eseguito sempre dopo il blocco try (-catch), se viene generata un'eccezione o meno.

Nel tuo esempio non hai mostrato il terzo possibile costrutto:

try {
    // try to execute this statements...
}
catch( SpecificException e ) {
    // if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
    // if a more general exception was thrown, handle it here
}
finally {
    // here you can clean things up afterwards
}

E, come dice @codeca nel suo commento, non c'è modo di accedere all'eccezione all'interno del blocco finalmente, perché il blocco finale viene eseguito anche se non ci sono eccezioni.

Ovviamente potresti dichiarare una variabile che contiene l'eccezione al di fuori del tuo blocco e assegnare un valore all'interno del blocco catch. Successivamente puoi accedere a questa variabile all'interno del tuo blocco finalmente.

Throwable throwable = null;
try {
    // do some stuff
}
catch( Throwable e ) {
    throwable = e;
}
finally {
    if( throwable != null ) {
        // handle it
    }
}

11
Un corollario a ciò è che non puoi accedere a Throwabledal finallyblocco, perché potrebbe non esserci un file Throwable.
Dean Harding

11

Queste non sono variazioni, sono cose fondamentalmente diverse. finallyviene eseguito sempre , catchsolo quando si verifica un'eccezione.


7

Infine e i blocchi di cattura sono abbastanza diversi:

  • All'interno del blocco catch puoi rispondere all'eccezione generata. Questo blocco viene eseguito solo se c'è un'eccezione non gestita e il tipo corrisponde a quello o è una sottoclasse di quello specificato nel parametro del blocco catch.
  • Infine verrà sempre eseguito dopo aver provato e catturato i blocchi indipendentemente dal fatto che sia stata sollevata un'eccezione o meno.

Così

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if ExceptionA 
  // was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in try 
  // and not handled by first catch block
}

si differenzia da

try {
  //some code
}
finally {
  // Gets executed whether or not 
  // an exception was thrown in try block
}

in modo significativo.

Se definisci un blocco try devi definire

  1. un blocco alla fine, o
  2. uno o più blocchi di cattura, o
  3. uno o più blocchi di cattura e un blocco finale

Quindi anche il seguente codice sarebbe valido:

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if 
  // ExceptionA was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in 
  // try and not handled by first catch block
}
//even more catch blocks
finally {
  // Gets executed whether or not an 
  // exception was thrown in try block
}

4

try viene utilizzato per eseguire un metodo che può generare un'eccezione

catch è usato per "catturare" fermare quell'eccezione

finally viene utilizzato per qualsiasi ripulitura necessaria da quell'eccezione che viene catturata o meno

try{
    myObject.riskyMethod(); // run a method that may throw an exception
}
catch(Exception ex){
    myLogger.log(ex.Message); // "catch" stop that exception
}
finally{
    myObject = null; // clean up needed from that exception being caught
}

3
try {
    statements;
} catch (exceptionType1 e1) {      // one or multiple
    statements;                 
} catch (exceptionType2 e2) {
    statements;
}    
...
} finally {                                 // one or none
    statements;
}
  1. Tutte le istruzioni try devono includere una clausola catch o una clausola finalmente
  2. Può avere più clausole catch ma solo una infine
  3. Durante qualsiasi esecuzione, se si verificano errori, il Controllo viene trasferito al blocco Catch appropriato ed esegue le istruzioni e il blocco Infine viene eseguito.

Non importa cosa Il blocco Infine viene sempre eseguito, quindi in generale, viene utilizzato il blocco Finale, quando si hanno sessioni, connessioni al database o file o socket sono aperti, verrà inserito il codice per la chiusura di tali connessioni. Questo è solo per assicurarsi che in un'applicazione non ci siano perdite di memoria o che non si verifichino altri problemi.


3

Infine e i blocchi di cattura sono abbastanza diversi:

All'interno del blocco catch puoi rispondere all'eccezione generata. Questo blocco viene eseguito solo se c'è un'eccezione non gestita e il tipo corrisponde a quello o è una sottoclasse di quello specificato nel parametro del blocco catch. Infine verrà sempre eseguito dopo aver provato e catturato i blocchi indipendentemente dal fatto che sia stata sollevata un'eccezione o meno.


2

Nella mia ricerca Infine, il blocco viene sempre eseguito e viene principalmente "utilizzato per la chiusura di eventuali connessioni aperte" e per distruggere qualcosa che è in esecuzione inutilmente.


2

Generalmente quando usiamo risorse come stream, connessioni ecc. Dobbiamo chiuderle esplicitamente utilizzando finalmente block. Nel programma fornito di seguito stiamo leggendo i dati da un file utilizzando FileReader e lo stiamo chiudendo utilizzando finalmente block.

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]){
      FileReader fr=null;       
      try{
         File file=new File("file.txt");
         fr = new FileReader(file);  char [] a = new char[50];
         fr.read(a); // reads the content to the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }
       finally{ 
          try{
              fr.close();
          }catch(IOException ex){       
               ex.printStackTrace();
           }
       }
    }

}

Forse altri ragazzi come me hanno cercato qualcosa del genere.

Informazioni da questa pagina tutpoint


1

Infine il blocco viene sempre eseguito. Il blocco di cattura viene eseguito solo quando viene rilevata un'eccezione che corrisponde al parametro dei blocchi.


1

Anche nel primo modulo potresti registrarlo nel metodo chiamante. Quindi non c'è un grande vantaggio a meno che tu non voglia fare un trattamento speciale proprio lì.


0

Il blocco di prova conterrà le istruzioni che solleveranno un'eccezione. Il blocco catch manterrà il riferimento generato dal blocco try e i messaggi richiesti vengono generati dal blocco catch. Infine il blocco viene utilizzato anche per chiudere le risorse utilizzate come chiusura io, chiusura file, chiusura dB .. In Java -9 la risorsa try-with migliorata è arrivata dove le risorse sono dichiarate al di fuori della try..in enchanced try with resource il blocco catch è obbligatorio

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.