¿Existe una forma elegante de manejar las excepciones que se lanzan en finally
bloque?
Por ejemplo:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
¿Cómo evitas el try
/ catch
en el finally
bloque?
Resource
=>Closeable
?Normalmente uso uno de los
closeQuietly
métodos enorg.apache.commons.io.IOUtils
:fuente
Si está usando Java 7 y lo
resource
implementaAutoClosable
, puede hacer esto (usando InputStream como ejemplo):fuente
Podría decirse que es un poco exagerado, pero tal vez útil si está permitiendo que surjan excepciones y no puede registrar nada desde su método (por ejemplo, porque es una biblioteca y prefiere dejar que el código de llamada maneje las excepciones y el registro):
ACTUALIZACIÓN: Revisé esto un poco más y encontré una excelente publicación de blog de alguien que claramente ha pensado en esto más que yo: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make -mess-of-stream.html Va un paso más allá y combina las dos excepciones en una, lo que podría ser útil en algunos casos.
fuente
ignore
excepciónA partir de Java 7, ya no es necesario cerrar explícitamente los recursos en un bloque finalmente , sino que puede usar la sintaxis try -with-resources. La declaración try-with-resources es una declaración try que declara uno o más recursos. Un recurso es un objeto que debe cerrarse después de que el programa haya terminado con él. La declaración try-with-resources asegura que cada recurso se cierre al final de la declaración. Cualquier objeto que implemente java.lang.AutoCloseable, que incluye todos los objetos que implementan java.io.Closeable, se puede usar como recurso.
Suponga el siguiente código:
Si ocurre alguna excepción , se llamará al método close en cada uno de estos tres recursos en orden opuesto al que fueron creados. Significa que el método de cierre se llamará primero para ResultSetm, luego la Declaración y al final para el objeto Connection.
También es importante saber que se suprimen las excepciones que ocurren cuando se llama automáticamente a los métodos de cierre. Estas excepciones suprimidas se pueden recuperar mediante el método getsuppressed () definido en la clase Throwable .
Fuente: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
fuente
Ignorar las excepciones que ocurren en un bloque 'finalmente' es generalmente una mala idea a menos que uno sepa cuáles serán esas excepciones y qué condiciones representarán. En el
try/finally
patrón de uso normal , eltry
bloque coloca las cosas en un estado que el código externo no espera, y elfinally
bloque restaura el estado de esas cosas a lo que espera el código externo. El código externo que detecta una excepción generalmente esperará que, a pesar de la excepción, todo se haya restaurado a unnormal
estado. Por ejemplo, suponga que algún código inicia una transacción y luego intenta agregar dos registros; el bloque "finalmente" realiza una operación de "reversión si no se ha confirmado". Una persona que llama puede estar preparada para que ocurra una excepción durante la ejecución de la segunda operación "agregar", y puede esperar que si detecta dicha excepción, la base de datos estará en el estado en el que estaba antes de intentar cualquier operación. Sin embargo, si se produce una segunda excepción durante la reversión, podrían suceder cosas malas si la persona que llama hace suposiciones sobre el estado de la base de datos. El error de reversión representa una crisis importante , una que no debe ser detectada por el código esperando una simple excepción de "No se pudo agregar el registro".Mi inclinación personal sería tener un método de captura de las excepciones que ocurren y envolverlas en una "CleanupFailedException", reconociendo que tal falla representa un problema importante y que tal excepción no debe tomarse a la ligera.
fuente
Una solución, si las dos excepciones son dos clases diferentes
Pero a veces no se puede evitar este segundo intento. p. ej. para cerrar una corriente
fuente
¿Por qué quiere evitar el bloqueo adicional? Dado que el bloque finalmente contiene operaciones "normales" que pueden generar una excepción Y desea que el bloque finalmente se ejecute por completo, TIENE que detectar excepciones.
Si no espera que el bloque finalmente arroje una excepción y no sabe cómo manejar la excepción de todos modos (simplemente volcaría el seguimiento de la pila) deje que la excepción burbujee en la pila de llamadas (elimine el try-catch de la última bloquear).
Si desea reducir la escritura, puede implementar un bloque try-catch externo "global", que capturará todas las excepciones lanzadas en los bloques finalmente:
fuente
Después de mucha consideración, encuentro mejor el siguiente código:
Ese código garantiza lo siguiente:
fuente
Si puede, primero debe probar para evitar la condición de error.
Además, probablemente solo debería detectar excepciones de las que puede recuperarse, si no puede recuperar, deje que se propague al nivel superior de su programa. Si no puede probar una condición de error, tendrá que rodear su código con un bloque try catch como ya lo ha hecho (aunque recomendaría detectar errores específicos esperados).
fuente
Podrías refactorizar esto en otro método ...
fuente
Yo suelo hacer esto:
Justificación: si terminé con el recurso y el único problema que tengo es cerrarlo, no hay mucho que pueda hacer al respecto. Tampoco tiene sentido matar todo el hilo si de todos modos he terminado con el recurso.
Este es uno de los casos en los que, al menos para mí, es seguro ignorar esa excepción marcada.
Hasta el día de hoy no he tenido ningún problema para usar este idioma.
fuente
Trabajo hecho. Sin pruebas nulas. Captura única, incluye excepciones de adquisición y liberación. Por supuesto, puede usar el idioma Execute Around y solo tiene que escribirlo una vez para cada tipo de recurso.
fuente
Cambiar
Resource
de la mejor respuesta aCloseable
Implementos de corrientes
Closeable
Por lo tanto, puede reutilizar el método para todas las corrientesfuente
Encontré una situación similar en la que no podía usar try con recursos, pero también quería manejar la excepción proveniente del cierre, no solo registrarla e ignorarla como lo hace el mecanismo closeQuietly. en mi caso, no estoy tratando con un flujo de salida, por lo que la falla al cerrar es de más interés que un flujo simple.
fuente