Recientemente me sorprendió descubrir que es posible tener una declaración de devolución en un bloque finalmente en Java.
Parece que mucha gente piensa que es algo malo hacer como se describe en ' No regrese en una cláusula final '. Rascando un poco más, también encontré ' El retorno de Java no siempre ', que muestra algunos ejemplos bastante horribles de otros tipos de control de flujo en bloques finalmente.
Entonces, mi pregunta es, ¿alguien puede darme un ejemplo donde una declaración de retorno (u otro control de flujo) en un bloque finalmente produzca un código mejor / más legible?
fuente
Hace muchos años tuve dificultades para localizar un error que fue causado por esto. El código era algo así como:
Lo que sucedió es que la excepción se arrojó en algún otro código. Fue capturado y registrado y vuelto a lanzar dentro del
somethingThatThrewAnException()
método. Pero la excepción no se propagaba al pasadoproblemMethod()
. Después de MUCHO tiempo de mirar esto, finalmente lo rastreamos hasta el método de retorno. El método de retorno en el bloque finalmente básicamente estaba deteniendo la propagación de la excepción que ocurrió en el bloque try aunque no se detectó.Como han dicho otros, aunque es legal regresar de un bloque finalmente de acuerdo con las especificaciones de Java, es algo MALO y no debe hacerse.
fuente
javac le avisará de retorno finalmente si usa -Xlint: finalmente. Originalmente, javac no emitía advertencias: si algo estaba mal con el código, debería fallar al compilar. Desafortunadamente, la compatibilidad con versiones anteriores significa que no se puede prohibir la tontería ingeniosa imprevista.
Se pueden generar excepciones desde finalmente bloques, pero en ese caso el comportamiento exhibido es casi seguro lo que desea.
fuente
Agregar estructuras de control y retornos a los bloques finalmente {} son solo otro ejemplo de abusos "solo porque puedes" que se encuentran dispersos en prácticamente todos los lenguajes de desarrollo. Jason tenía razón al sugerir que podría convertirse fácilmente en una pesadilla de mantenimiento: los argumentos en contra de los primeros retornos de las funciones se aplican más a este caso de "retornos tardíos".
Finalmente, existen bloques para un propósito, para permitirle ordenar completamente por sí mismo, sin importar lo que sucedió en todo el código anterior. Principalmente, esto es cerrar / liberar punteros de archivos, conexiones de bases de datos, etc., aunque pude ver que se estira para decir que se agrega una auditoría a medida.
Cualquier cosa que afecte el retorno de la función debería estar en el bloque try {}. Incluso si tuviera un método mediante el cual verificó un estado externo, realizó una operación que consume mucho tiempo, luego verificó ese estado nuevamente en caso de que se volviera inválido, aún querría la segunda verificación dentro del intento {}, si finalmente se quedó adentro {} y la operación larga falló, entonces verificaría ese estado por segunda vez innecesariamente.
fuente
Una simple prueba de Groovy:
Salida:
Pregunta:
Un punto interesante para mí fue ver cómo Groovy trata con los retornos implícitos. En Groovy es posible "regresar" de un método simplemente dejando un valor al final (sin retorno). ¿Qué crees que sucede si descomentas el runningThreads.remove (..) en la declaración de ? ¿Esto sobrescribirá el valor de retorno regular ("OK") y cubrirá la excepción ?!
fuente
Volver desde el interior de un
finally
bloque haráexceptions
que se pierda.Una declaración de devolución dentro de un bloque finalmente hará que se descarte cualquier excepción que pueda lanzarse en el bloque try o catch.
De acuerdo con la especificación del lenguaje Java:
Nota: Según JLS 14.17 : una declaración de devolución siempre se completa abruptamente.
fuente