¿Se ejecuta finalmente un bloqueo incluso si lanzas una nueva Excepción?

142

En este código se someVarestablecerá incluso si se ejecuta el bloque catch y se lanza la segunda excepción?

public void someFunction() throws Exception {
    try {
        //CODE HERE
    } catch (Exception e) {
        Log.e(TAG, "", e);
        throw new Exception(e);
    } finally {
        this.someVar= true;
    }
}
jax
fuente
2
Debido a que hay circunstancias en las que el comportamiento no es el esperado, según lo indicado por @GaryF
jax
1
Vale la pena señalar que el bloque final puede no ejecutarse como se esperaba si arroja una excepción o hace un retorno.
Peter Lawrey

Respuestas:

184

Sí, los bloques finalmente siempre se ejecutan ... excepto cuando:

  • El hilo que ejecuta el bloque try-catch-finally se mata o se interrumpe
  • Tu usas System.exit(0);
  • La VM subyacente se destruye de alguna otra manera.
  • El hardware subyacente es inutilizable de alguna manera.

Además, si un método en su bloque finalmente arroja una excepción no detectada, entonces nada más se ejecutará (es decir, la excepción se lanzará como lo haría en cualquier otro código). Un caso muy común donde esto sucede es java.sql.Connection.close().

Por otro lado, supongo que la muestra de código que ha utilizado es simplemente un ejemplo, pero tenga cuidado de poner la lógica real dentro de un bloque finalmente. El último bloque está destinado a la limpieza de recursos (cierre de conexiones de base de datos, liberación de identificadores de archivos, etc.), no para la lógica de ejecución obligatoria. Si debe ejecutarse, hágalo antes del bloque try-catch, lejos de algo que pueda generar una excepción, ya que su intención es casi funcionalmente la misma.

GaryF
fuente
44
¿Qué quiere decir aquí con "El hilo que ejecuta el bloque try-catch-finally se [...] interrumpe"? Tal vez esa documentación esté mal redactada, pero Thread.interrupt () no hará que se omita el bloque final, ya sea que se elimine del bloque try o catch. ¿Utiliza esto "interrumpido" para significar algo más violento, como Thread.stop ()?
Joe Kearney el
@ Joe: Sí, creo que la documentación está un poco mal redactada aquí, y que significan una interrupción general de la actividad del hilo.
GaryF
@GaryF - Creo que estás citando a JLS. La redacción del JLS es a veces un poco extraña, pero normalmente encontrará que el significado de la terminología extraña se define claramente en otra parte del documento. El JLS es una especificación y tiene como objetivo principal la precisión (en lugar de la legibilidad).
Stephen C
1
@Stephen C - En realidad, eso vino del tutorial de JavaSE (vinculado por otros). Puede estar redactado de manera similar en el JLS, pero no puedo encontrar la parte relevante. Esperaba esto en el capítulo 11 (Excepciones), el capítulo 14 (Declaraciones) o el capítulo 15 (Expresiones), pero no puedo ver nada que se refiera explícitamente a las interrupciones. Ciertamente estaría interesado en ver eso.
GaryF
1
@GaryF - Ya veo. En realidad, el JLS habla sobre la terminación "normal" y "abrupta" de las declaraciones, y hay una sección (14.1) que define la terminología. El comportamiento de finallyentonces se especifica en términos de terminaciones normales y abruptas.
Stephen C
10

Si.

Ver la documentación :

El bloque finalmente siempre se ejecuta cuando sale el bloque try.

Excepciones:

Nota: Si la JVM sale mientras se está ejecutando el código try o catch, entonces el bloque finalmente puede no ejecutarse. Del mismo modo, si el subproceso que ejecuta el código de prueba o captura se interrumpe o finaliza, el bloque finalmente puede no ejecutarse aunque la aplicación en su conjunto continúe.

froadie
fuente
2

Finalmente, el bloque siempre se ejecuta.

public class ExceptionTest {

public static void someFunction(String input) throws Exception {
    try {
        if( input.equals("ABC") ) {
            System.out.println("Matched");
        }
    } catch (Exception e) {
        throw new Exception(e);
    } finally {
        System.out.println("Input Is "+input+" Finally Executed!!!");
    }
}

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
        System.out.println("********* Test with VALUE ********* ");
        someFunction("ABC");
        System.out.println("\r\n********* Test with NULL  ********* ");
        someFunction(null);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

Java Try Catch Finalmente bloquear con Throw

Vasanth Umapathy
fuente
2

Finalmente siempre se ejecuta, no importa cuál sea su caso, es decir

  • bloque try-catch-finally
  • tiros

Para excepciones no marcadas, Java no exige el manejo de errores. esta es la razón, si se produce una excepción no verificada en el bloque finalmente y no se realiza ningún tratamiento para eso, entonces el código escrito debajo de este punto (donde se ha producido el error) no se ejecutará.

Por lo tanto, sugiero manejar siempre todas las excepciones, ya sea que esté marcado o desmarcado. De esta forma, puede asegurarse de que el bloqueo de código finalmente también se ejecute sin importar si también se produce una excepción no verificada. usted tiene un lugar en la captura de sub-nido y finalmente bloquea para realizar su trabajo necesario.

yug
fuente
1

Si. finallyEl bloque se ejecuta siempre, excepto en el caso de que llame a System.exit () porque detiene Java VM.

Vladimir Ivanov
fuente
Los ganchos de apagado todavía se llaman después de System.exit (), pero todos los subprocesos que no son del sistema se detienen.
Peter Lawrey