Teniendo en cuenta este código, ¿puedo estar absolutamente seguro de que el finally
bloque siempre se ejecuta, sin importar lo que something()
sea?
try {
something();
return success;
}
catch (Exception e) {
return failure;
}
finally {
System.out.println("I don't know if this will get printed out");
}
java
error-handling
return
try-catch-finally
jonny cinco
fuente
fuente
probably
en su lugar.finally
; finalizador == elfinalize()
método.Respuestas:
Sí,
finally
se llamará después de la ejecución de los bloques de códigotry
ocatch
.Los únicos momentos
finally
que no se llamarán son:System.exit()
Runtime.getRuntime().halt(exitStatus)
try
ocatch
kill -9 <pid>
en UNIXfinally
bloque va a ser ejecutado por un subproceso de demonio y todos los demás subprocesos que no son de demonio salen antes,finally
se llamafuente
thread.stop()
, no necesariamente evitafinally
que se ejecute el bloque.finally
bloque se llamará después deltry
bloque y antes de que el control pase a las siguientes declaraciones? Eso es consistente con el bloque try que involucra un ciclo infinito y, por lo tanto, el bloque finalmente nunca se invoca.Código de ejemplo:
Salida:
fuente
finally
cláusula -conreturn 2;
(Error del compilador).Además, aunque es una mala práctica, si hay una declaración de devolución dentro del bloque finalmente, prevalecerá sobre cualquier otra devolución del bloque regular. Es decir, el siguiente bloque devolvería falso:
Lo mismo con lanzar excepciones desde el último bloque.
fuente
Aquí están las palabras oficiales de la Especificación del lenguaje Java.
14.20.2. Ejecución de try-finally y try-catch-finally
La especificación para
return
realmente hace esto explícito:JLS 14.17 La declaración de devolución
fuente
Además de las otras respuestas, es importante señalar que 'finalmente' tiene el derecho de anular cualquier excepción / valor devuelto por el bloque try..catch. Por ejemplo, el siguiente código devuelve 12:
Del mismo modo, el siguiente método no arroja una excepción:
Si bien el siguiente método lo arroja:
fuente
OutOfMemoryError
? ;)return retVal
después delfinally
bloque, aunque eso, por supuesto, supone que suprimió algunas otras excepciones porque el código no tendría sentido de otra manera.Intenté el ejemplo anterior con una ligera modificación.
Las salidas del código anterior:
Esto se debe a que cuando
return i;
se ejecutai
tiene un valor 2. Después de esto, elfinally
bloque se ejecuta donde se asigna 12i
y luegoSystem.out
se ejecuta out.Después de ejecutar el
finally
bloque, eltry
bloque devuelve 2, en lugar de devolver 12, porque esta declaración de retorno no se ejecuta nuevamente.Si va a depurar el código en Eclipse entonces obtendrá una sensación de que después de la ejecución
System.out
delfinally
bloque de lareturn
declaración deltry
bloque se ejecuta de nuevo. Pero este no es el caso. Simplemente devuelve el valor 2.fuente
i
no fuera un primitivo, sino un objeto entero?Aquí hay una elaboración de la respuesta de Kevin . Es importante saber que la expresión a devolver se evalúa antes
finally
, incluso si se devuelve después.Salida:
fuente
finally
. Calcular el valor de retorno (printX()
aquí) todavía viene antes.System.out.println("finally trumps return... sort of");
conSystem.out.print("finally trumps return in try"); return 42;
Esa es la idea de un bloque finalmente. Te permite asegurarte de hacer limpiezas que de otro modo podrían saltarse porque regresas, entre otras cosas, por supuesto.
Finalmente se llama independientemente de lo que ocurra en el bloque de prueba (a menos que llame
System.exit(int)
o la máquina virtual Java se apague por alguna otra razón).fuente
Una forma lógica de pensar en esto es:
fuente
finalmente siempre se ejecuta a menos que haya una terminación anormal del programa (como llamar a System.exit (0) ..). entonces, tu sysout se imprimirá
fuente
También un retorno finalmente rechazará cualquier excepción. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
fuente
El último bloque siempre se ejecuta a menos que haya una terminación anormal del programa, ya sea como resultado de un bloqueo de JVM o de una llamada a
System.exit(0)
.Además de eso, cualquier valor devuelto desde dentro del último bloque anulará el valor devuelto antes de la ejecución del último bloque, por lo tanto, tenga cuidado de verificar todos los puntos de salida cuando use try finally.
fuente
No, no siempre un caso de excepción es // System.exit (0); antes de que finalmente el bloque impida finalmente ser ejecutado.
fuente
Finalmente, siempre se ejecuta ese es el punto, solo porque aparece en el código después de la devolución no significa que así es como se implementa. El tiempo de ejecución de Java tiene la responsabilidad de ejecutar este código al salir del
try
bloque.Por ejemplo, si tiene lo siguiente:
El tiempo de ejecución generará algo como esto:
Si se produce una excepción no detectada, el
finally
bloque se ejecutará y la excepción continuará propagándose.fuente
Esto se debe a que asignó el valor de i como 12, pero no devolvió el valor de i a la función. El código correcto es el siguiente:
fuente
Porque un bloque finalmente siempre se llamará a menos que llame
System.exit()
(o el subproceso se bloquea).fuente
De manera concisa, en la documentación oficial de Java (haga clic aquí ), está escrito que:
fuente
ENTRADA:
SALIDA:
fuente
Sí, lo llamarán. Ese es el punto de tener finalmente una palabra clave. Si saltar fuera del bloque try / catch podría saltarse el bloque finalmente, era lo mismo que colocar System.out.println fuera del try / catch.
fuente
Sí, finalmente el bloque siempre se ejecuta. La mayoría de los desarrolladores usan este bloqueo al cerrar la conexión de la base de datos, el objeto del conjunto de resultados, el objeto de la declaración y también los utiliza en la hibernación de Java para revertir la transacción.
fuente
NO SIEMPRE
La especificación del lenguaje Java se describe cómo
try
-catch
-finally
ytry
-catch
bloques trabajan en 14.20.2En ningún lugar se especifica que el
finally
bloque se ejecuta siempre. Pero en todos los casos en los que eltry
-catch
-finally
ytry
-finally
bloques completos se especifica que antes de la terminaciónfinally
debe ser ejecutado.El JLS no garantiza que FIN se ejecute después de CODE . El JLS garantiza que si se ejecutan CODE y NEXT , FIN siempre se ejecutará después de CODE y antes de NEXT .
¿Por qué JLS no garantiza que el
finally
bloque siempre se ejecute después deltry
bloque? Porque es imposible Es poco probable pero posible que la JVM sea abortada (matar, estrellarse, apagarse) justo después de completar eltry
bloque pero antes de la ejecución delfinally
bloque. JLS no puede hacer nada para evitar esto.Por lo tanto, cualquier software que, para su correcto comportamiento, dependa de que los
finally
bloques se ejecuten siempre después de quetry
se completen sus bloques.return
las instrucciones en eltry
bloque son irrelevantes para este problema. Si la ejecución alcanza el código después detry
-catch
,finally
se garantiza que elfinally
bloque se habrá ejecutado antes, con o sinreturn
instrucciones dentro deltry
bloque.fuente
Sí lo hará No importa lo que ocurra en el bloque try o catch a menos que se llame System.exit () o JVM se bloquee. Si hay alguna declaración de retorno en el (los) bloque (s), finalmente se ejecutará antes de esa declaración de retorno.
fuente
Sí lo hará. El único caso que no será es que JVM salga o se bloquee
fuente
Agregar a la respuesta de @ vibhash como ninguna otra respuesta explica lo que sucede en el caso de un objeto mutable como el siguiente.
Saldrá
fuente
Intenté esto, es de un solo hilo.
El
main
Thread
estará enwait
estado para siempre, porfinally
lo tanto , nunca será llamado ,entonces la salida de la consola no
print
String
: despuéswait()
ofinally
De acuerdo con @Stephen C, el ejemplo anterior es uno de los 3er caso mencionados aquí :
Agregando algunas más posibilidades de bucle infinito en el siguiente código:
Caso 2: si la JVM se bloquea primero
Ref: ¿Cómo se bloquea un JVM?
Caso 6: si el
finally
bloque va a ser ejecutado por un demonioThread
y se llama a todas las otrasThreads
salidas que no sean demonios antesfinally
.salida: Esto no imprime "finalmente", lo que implica que "Finalmente bloque" en "hilo de demonio" no se ejecutó
fuente
Considere el siguiente programa:
A partir de Java 1.8.162, el bloque de código anterior proporciona el siguiente resultado:
Esto significa que usar
finally
para liberar objetos es una buena práctica como el siguiente código:fuente
sb.setLength(0)
finalmente?sb = null;
solo agrega código innecesario. Entiendo que quiere decir que unfinally
bloque es un buen lugar para liberar recursos como una conexión de base de datos o algo así, pero tenga en cuenta que su ejemplo podría confundir a los recién llegados.System.out.println("---AGAIN2---");
System.out.println(sb);
y ahora está más claro. Tal como estaba, el resultado estaba en contra de su tesis: p También agregué a su respuesta, pero la edición debe ser aceptada por un moderador o alguien así. De lo contrario, puede agregarlosEso es realmente cierto en cualquier idioma ... finalmente siempre se ejecutará antes de una declaración de devolución, sin importar dónde esté esa devolución en el cuerpo del método. Si ese no fuera el caso, el bloque finalmente no tendría mucho significado.
fuente
Además del punto sobre el retorno al reemplazar finalmente un retorno en el bloque try, lo mismo se aplica a una excepción. Un bloque finalmente que arroja una excepción reemplazará una devolución o excepción lanzada desde el bloque try.
fuente
finally
ejecutará y eso es seguro.finally
no se ejecutará en los siguientes casos:caso 1 :
Cuando estás ejecutando
System.exit()
.caso 2:
Cuando tu JVM / Thread se bloquea.
caso 3:
Cuando su ejecución se detiene en el medio manualmente.
fuente
fuente