Java Try Catch Finalmente bloquea sin Catch

125

Estoy revisando un nuevo código. El programa tiene una prueba y finalmente solo un bloqueo. Dado que el bloque catch está excluido, ¿cómo funciona el bloque try si encuentra una excepción o algo arrojable? ¿Simplemente va directamente al bloque finalmente?

NullPointer0x00
fuente
2
posible duplicado de la diferencia entre try-finally y try-catch
Pablo Fernández
25
@mP Todos deberían hacer revisiones de código y hacerles preguntas es cómo aprender y mejorar.
Carl Pritchett

Respuestas:

130

Si alguno de los códigos en el bloque try puede generar una excepción marcada, debe aparecer en la cláusula throws de la firma del método. Si se lanza una excepción no marcada, se elimina del método.

El último bloque siempre se ejecuta, ya sea que se lance una excepción o no.

duffymo
fuente
11
El primer párrafo no es necesariamente cierto. Los bloques de prueba pueden estar anidados. Cualquier excepción no detectada, no verificada o no, saldrá del método.
Andy Thomas
44
Los bloques de prueba se pueden anidar, pero no lo recomendaría. No escribo código de esa manera.
duffymo
2
@duffymo: ¿Cuál es el significado de "borrado del método"?
HoyHe aprendido
55
@ Y solo un poco de lenguaje no técnico para "lanzar una excepción".
duffymo
2
No ignorado Pase la cadena del método.
duffymo
93

Una pequeña nota sobre try/ finally: El finalmente siempre se ejecutará a menos que

  • System.exit() se llama.
  • La JVM se bloquea.
  • El try{}bloque nunca termina (por ejemplo, bucle sin fin).
Peter Lawrey
fuente
44
¿Qué hay de try{..} catch{ throw ..} finally{..}? Creo que finalmente no será ejecutado
sbeliakov
10
En ese caso, finalmente se seguirá llamando. Solo se pierde la excepción original.
Peter Lawrey
Finalmente tampoco se ejecutará si llama a System.exit () antes.
mmirror
2
@jyw Eso es lo que quise decir con el primer elemento de la lista anterior.
Peter Lawrey
Tengo que decir que esto cubre todas las bases.
Oscar Bravo
39

La especificación del lenguaje Java (1) describe cómo try-catch-finallyse ejecuta. No tener captura es equivalente a no tener una captura capaz de atrapar el Lanzamiento dado.

  • Si la ejecución del bloque try se completa abruptamente debido a un lanzamiento de un valor V, entonces hay una opción:
    • Si el tipo de tiempo de ejecución de V es asignable al parámetro de cualquier cláusula catch de la declaración try, entonces ...
      ...
    • Si el tipo de V en tiempo de ejecución no es asignable al parámetro de ninguna cláusula catch de la instrucción try, entonces se ejecuta el bloque finalmente . Entonces hay una opción:
      • Si el bloque finalmente se completa normalmente, entonces la instrucción try se completa abruptamente debido a un lanzamiento del valor V.
      • Si el bloque finalmente se completa abruptamente por la razón S, entonces la instrucción try se completa abruptamente por la razón S (y el lanzamiento del valor V se descarta y se olvida).

(1) Ejecución de try-catch-finally

usuario85421
fuente
16

El interno finalmente se ejecuta antes de lanzar la excepción al bloque externo.

public class TryCatchFinally {

  public static void main(String[] args) throws Exception {

    try{
        System.out.println('A');
        try{
            System.out.println('B');
            throw new Exception("threw exception in B");
        }
        finally
        {
            System.out.println('X');
        }
        //any code here in the first try block 
        //is unreachable if an exception occurs in the second try block
    }
    catch(Exception e)
    {
        System.out.println('Y');
    }
    finally
    {
        System.out.println('Z');
    }
  }
}

Resultados en

A
B
X
Y
Z
comprador
fuente
6

El bloque finalmente siempre se ejecuta después de que finaliza el bloque try, ya sea que el try finalice de manera normal o anormal debido a una excepción, er, arrojable.

Si alguno de los códigos del bloque de prueba genera una excepción, el método actual simplemente vuelve a lanzar (o continúa lanzando) la misma excepción (después de ejecutar el bloque finalmente).

Si el bloque finalmente arroja una excepción / error / lanzamiento, y ya hay un lanzamiento pendiente, se pone feo. Francamente, olvido exactamente lo que sucede (tanto por mi certificación hace años). Yo pienso ambos lanzamientos se vinculan entre sí, pero hay que hacer un vudú especial (es decir, una llamada al método que tendría que buscar) para obtener el problema original antes de que el "finalmente" vomitara, er, vomitara.

Por cierto, intentar / finalmente es algo bastante común para la gestión de recursos, ya que Java no tiene destructores.

P.ej -

r = new LeakyThing();
try { useResource( r); }
finally { r.release(); }  // close, destroy, etc

"Finalmente", un consejo más: si no se molestan en poner en una captura, ya sea específica de captura (esperado) subclases arrojadizos, o simplemente coger "Throwable", no "excepción", por un cajón de sastre trampa de error general. Demasiados problemas, tales como tonterías de reflexión, arrojan "Errores", en lugar de "Excepciones", y esos se deslizarán por cualquier "capturar todo" codificado como:

catch ( Exception e) ...  // doesn't really catch *all*, eh?

haz esto en su lugar:

catch ( Throwable t) ...
Roboprog
fuente
Vea la respuesta de Carlos Heuberger a continuación para la parte fea.
mplwork
3

Las versiones de Java anteriores a la versión 7 permiten estas tres combinaciones de try-catch-finally ...

try - catch
try - catch - finally
try - finally

finallyEl bloque siempre se ejecutará sin importar lo que esté sucediendo en el bloque tryor / and catch. así que si no hay catchbloque, la excepción no se manejará aquí.

Sin embargo, aún necesitará un controlador de excepciones en algún lugar de su código, a menos que, por supuesto, desee que su aplicación se bloquee por completo. Depende de la arquitectura de su aplicación exactamente dónde está ese controlador.

  • El bloque de prueba de Java debe ir seguido de un bloque catch o finalmente.
  • Para cada bloque try puede haber cero o más bloques catch, pero solo un bloque finalmente.
  • El último bloque no se ejecutará si el programa sale (ya sea llamando a System.exit () o causando un error fatal que hace que el proceso se cancele).
roottraveller
fuente
1
"antes de permitir la versión 7" ¿estás insinuando que Java 7 y Java 8 no permiten estas tres combinaciones? Dudo que sea eso lo que quieres decir, pero eso es lo que implica tu respuesta.
Loduwijk
¿se ejecuta finalmente el bloque si hay una declaración de retorno en el bloque try?
Rahul Yadav
@Rahul Sí, finalmente se llamará. Ref: stackoverflow.com/questions/65035/…
roottraveller
1
@Aaron: nueva sintaxis para try-with-resource que llama automáticamente .close () en cualquier cosa construida dentro de parens justo después de la palabra clave try.
Roboprog
2

¿Cómo funciona el bloque try si encuentra una excepción o algo arrojable?

La excepción se elimina del bloque, como en cualquier otro caso en el que no se detecta.

El último bloque se ejecuta independientemente de cómo salga el bloque de prueba, independientemente de si hay capturas, independientemente de si hay una captura coincidente.

Los bloques catch y finalmente son partes ortogonales del bloque try. Puedes tener uno o ambos. ¡Con Java 7, no podrás tener ninguno!

Andy Thomas
fuente
1

¿No lo intentas con ese programa? Finalmente se bloqueará y ejecutará finalmente el bloqueo, pero la excepción no se manejará. ¡Pero esa excepción puede ser anulada en el bloque finalmente!

Abimaran Kugathasan
fuente
1

El bloque finalmente se ejecuta después de que se completa el bloque try. Si se arroja algo dentro del bloque try cuando sale, finalmente se ejecuta el bloque.

mP.
fuente
0

Dentro del trybloque escribimos códigos que pueden arrojar una excepción. El catchbloque es donde manejamos la excepción. El finallybloque siempre se ejecuta sin importar si se produce una excepción o no.

Ahora, si tenemos el bloque try-finally en lugar del bloque try-catch-finally, entonces la excepción no se manejará y después de que el bloque try en lugar del control vaya al bloque catch, finalmente se bloqueará. Podemos usar el bloque try-finally cuando no queremos hacer nada con la excepción.

Animesh Jaiswal
fuente
0

Independientemente de la excepción lanzada o no en trybloque, finallyse ejecutará el bloque. La excepción no sería atrapada.

kreker
fuente