Diferencia entre intentar-finalmente y tratar-atrapar

91

Cuál es la diferencia entre

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

y

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

Me gusta más la segunda versión porque me da acceso al Throwable. ¿Existe alguna diferencia lógica o una convención preferida entre las dos variaciones?

Además, ¿hay alguna forma de acceder a la excepción desde la cláusula finalmente?

Vijay Kotari
fuente

Respuestas:

121

Estas son dos cosas diferentes:

  • El bloque catch solo se ejecuta si se lanza una excepción en el bloque try.
  • El bloque finalmente se ejecuta siempre después del bloque try (-catch), si se lanza una excepción o no.

En su ejemplo, no ha mostrado la tercera construcción posible:

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
}

Y, como dice @codeca en su comentario, no hay forma de acceder a la excepción dentro del bloque finalmente, porque el bloque finalmente se ejecuta incluso si no hay ninguna excepción.

Por supuesto, podría declarar una variable que contenga la excepción fuera de su bloque y asignar un valor dentro del bloque catch. Luego puede acceder a esta variable dentro de su bloque finalmente.

Throwable throwable = null;
try {
    // do some stuff
}
catch( Throwable e ) {
    throwable = e;
}
finally {
    if( throwable != null ) {
        // handle it
    }
}
tangenos
fuente
11
Un corolario de eso es que no puede acceder al Throwabledesde el finallybloque, porque es posible que no haya un Throwable.
Dean Harding
11

Estas no son variaciones, son cosas fundamentalmente diferentes. finallyse ejecuta siempre , catchsolo cuando ocurre una excepción.

Michiel Buddingh
fuente
7

Finalmente y los bloques de captura son bastante diferentes:

  • Dentro del bloque de captura, puede responder a la excepción lanzada. Este bloque se ejecuta solo si hay una excepción no controlada y el tipo coincide con el especificado en el parámetro del bloque catch o es una subclase del especificado.
  • Finalmente, siempre se ejecutará después de intentar y atrapar bloques, ya sea que se haya generado una excepción o no.

Entonces

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
}

difiere de

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

significativamente.

Si define un bloque de prueba, debe definir

  1. uno finalmente bloque, o
  2. uno o más bloques de captura, o
  3. uno o más bloques de captura y un bloque finalmente

Entonces el siguiente código también sería válido:

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
}
TheMorph
fuente
4

try se usa para ejecutar un método que puede generar una excepción

catch se utiliza para "capturar" detener esa excepción

finally se utiliza para cualquier limpieza necesaria a partir de que esa excepción se detecta o no

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
}
Kieran
fuente
3
try {
    statements;
} catch (exceptionType1 e1) {      // one or multiple
    statements;                 
} catch (exceptionType2 e2) {
    statements;
}    
...
} finally {                                 // one or none
    statements;
}
  1. Todas las declaraciones try deben incluir una cláusula catch o una cláusula finalmente
  2. Puede tener varias cláusulas catch pero solo una cláusula final
  3. Durante cualquier ejecución, si se produce algún error, el Control se transfiere al bloque Catch apropiado y ejecuta las declaraciones y finalmente se ejecuta el bloque.

No importa lo que El bloque Finalmente siempre se ejecuta, así que en general, el bloque Finalmente se usa, cuando tiene sesiones, conexiones de base de datos o archivos o sockets abiertos, entonces se colocará el código para cerrar esas conexiones. Esto es solo para asegurarse de que en una aplicación no se produzcan pérdidas de memoria o que no se produzcan otros problemas.

gmhk
fuente
3

Finalmente y los bloques de captura son bastante diferentes:

Dentro del bloque de captura, puede responder a la excepción lanzada. Este bloque se ejecuta solo si hay una excepción no controlada y el tipo coincide con el especificado en el parámetro del bloque catch o es una subclase del especificado. Finalmente, siempre se ejecutará después de intentar y atrapar los bloques, ya sea que se haya generado una excepción o no.

Tutorial de Android
fuente
2

En Mi investigación, el bloque Finalmente siempre se ejecuta y se usa principalmente para "cerrar las conexiones abiertas" y destruir algo que se está ejecutando innecesariamente.

Hari krishna
fuente
2

Generalmente, cuando usamos recursos como flujos, conexiones, etc., tenemos que cerrarlos explícitamente usando finalmente bloquear. En el programa que se muestra a continuación, leemos datos de un archivo usando FileReader y lo cerramos usando 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();
           }
       }
    }

}

Quizás otros tipos como yo buscamos algo como esto.

Información de esta página tutpoint


fuente
1

Finalmente, el bloque siempre se ejecuta. El bloque de captura se ejecuta solo cuando se detecta una excepción que coincide con el parámetro de bloques.

mkorpela
fuente
1

Incluso en el primer formulario, puede registrarlo en el método de llamada. Por lo tanto, no hay una gran ventaja a menos que desee realizar un manejo especial allí mismo.

fastcodejava
fuente
0

El bloque de prueba contendrá las declaraciones que generarán una excepción. El bloque catch contendrá la referencia lanzada desde el bloque try y los mensajes requeridos se generan desde el bloque catch. Finalmente, el bloque también se usa para cerrar los recursos utilizados, como el cierre de io, el cierre de archivos, el cierre de dB ... En Java, el recurso try-with mejorado -9 surgió donde los recursos se declaran fuera del try ... en el try mejorado con el bloque catch es obligatorio

srinija
fuente