studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones java exception-handling try-catch-finally

java - para - manual de programacion android pdf



prueba/finalmente sin captura y devuelve el valor (11)

Esta pregunta ya tiene una respuesta aquí:

Tengo un programa como el siguiente:

public class Main { public static void main(String[] args)throws Exception { int res = test(); System.out.println("after call , res = " + res) ; } public static int test()throws Exception { try { return 10/0; } finally { System.out.println("finally") ; } } }

después de ejecutar el programa anterior, el siguiente resultado vio en la consola:

finally Exception in thread "main" java.lang.ArithmeticException: / by zero at Main.test(Main.java:17) at Main.main(Main.java:7)

este comportamiento es normal porque se lanza una excepción al método principal.

Luego cambio el código de la siguiente manera:

public class Main { public static void main(String[] args)throws Exception { int res = test(); System.out.println("after call , res = " + res) ; } public static int test()throws Exception { try { return 10/0; } finally { System.out.println("finally") ; return 20; } } }

Cuando ejecuté el programa anterior vi el siguiente resultado en la consola:

finally after call , res = 20

Mi pregunta relacionada con el segundo formato. ¿Por qué cuando se devuelve finalmente el bloque, no se lanza la excepción al método principal?


En el primer programa, cuando se produce ArithmeticException en el bloque try, a continuación, llame al bloque finally y después de ejecutar el bloque finally, se produce una excepción. porque la excepción no es manejada por el programa. Segundo programa cuando finalmente el bloque ejecute después de que se ejecute la instrucción de retorno y no se produzca ninguna excepción porque después de que la instrucción devuelva, ejecute el compilador retorno en el método principal y la ejecución restante no se ejecutará en el bloque final Así que la excepción no ocurrirá.


La declaración de retorno en el bloque finally fue básicamente detener la excepción que ocurrió en el bloque try para que no se propague, a pesar de que no se detectó.

Pero el compilador de Java notifica advertencias cuando escribe este fragmento de código. Aunque las return statements siempre deben estar en el try block , y finally bloque es completamente para releasing/closing connections, pointers etc.

Parece la forma en que se comporta Java .

Echar un vistazo here


  1. Si usas return en la sección finally , pierdes la excepción. El método se terminará con un tipo normal de valor de retorno.
  2. Si no utiliza el método de return en la sección finally , en su caso, el método se terminará con la excepción.

El primer caso:

try { throw new Exception(); } finally { //Exception will be lost, normal shutdown of the method return; }

El segundo caso:

try { throw new Exception(); } finally { //Exception won''t be lost, we''ll get Exception in the main method }

El tercer caso:

try { throw new Exception(); } finally { throw new IOException(); // we lost Exception, IOException will be thrown }

Nota: utilizar la sección finally para lanzar excepciones o devolver valores es una mala práctica. Esta sección ha sido creada, por ejemplo, para cerrar recursos externos.


Cuando se lance su excepción, primero pasará por su bloque final.

Si su bloque final no regresa ni arroja nada, entonces se pasa la excepción original.

Si su bloque finally devuelve un valor, la excepción ya no se propaga en absoluto.


Desde el JLS (énfasis mío):

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 no es compatible con una clase de excepción detectable de cualquier cláusula catch de la instrucción try, se ejecuta el bloque finally. 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 la tirada de valor V se descarta y se olvida ).

Esto significa que si return dentro del bloque finally , el método regresa sin lanzar una excepción.

Además del return , hay otras declaraciones que pueden hacer que el bloque finally se complete de forma abrupta y se olvide de la excepción. Se definen en la sección 14.1 de JLS . Básicamente, es break , continue , return o una excepción (ya sea lanzada o causada por una declaración / método). El bloque completo de try/catch/finally se completa con este motivo.

Hay algunos casos más en la especificación de try/catch/finally , especialmente si no hay una excepción o si existe una cláusula catch correspondiente. Todo se reduce a los latidos, finally latidos de la trampa.


El return de Java no siempre regresa, this podría entretener.


En el primer caso, finalmente el bloque se ejecuta como su comportamiento, pero no detectó la excepción, pero la excepción se produce a través del método principal. Compruébalo a través de este ejemplo.

public class HelloWorld{ public static void main(String []args)throws Exception { try { int res = test(); System.out.println("after call , res = " + res) ; } catch(Exception ex) { System.out.println("Main Catch") ; } } public static int test()throws Exception { try { return 10/0; } finally { System.out.println("finally") ; } } }

En el código anterior, Main Catch se ejecutó.

En el segundo caso, devolvió el número, por lo que no hubo ninguna excepción en el método principal.


Mira la ejecución de intentar atrapar finalmente.

De la especificación del lenguaje java -jls-14.20.2

Si el tipo de tiempo de ejecución de V no es compatible con una clase de excepción detectable de cualquier cláusula catch de la instrucción try, se ejecuta el bloque finally. 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 la tirada de valor V se descarta y se olvida ).


Porque, finalmente, el bloque siempre se ejecuta , ya sea que se produzca una excepción o no, y si regresa de finally significa que está enviando su ejecución al método de llamada y pierde la Excepción . Por lo tanto, genera una advertencia también.


Si lees java doc de finalmente entonces dice:

permite al programador evitar que el código de limpieza se omita accidentalmente por una devolución, continuar o romper. Poner el código de limpieza en un bloque final es siempre una buena práctica, incluso cuando no se prevén excepciones.

Por lo tanto, si coloca un código de limpieza después del último bloque, no se llamará si hay una excepción.


Todo en un bloque finally se ejecuta antes de que se lance la excepción, por lo que si regresa en un bloque finally, la excepción no se lanzará en absoluto. Por lo general, es una mala idea regresar del bloque finalmente por esta razón.

Echa un vistazo a este blog para obtener información acerca de esto.