practices practice good exceptions custom catch best all java exception-handling throwable

practice - throw exception java



¿Es una mala práctica atrapar a Throwable? (13)

Aunque se describe como una práctica muy mala, a veces puede encontrar casos raros que no solo sean útiles sino también obligatorios. Aquí hay dos ejemplos.

En una aplicación web donde debe mostrar una página de significado de error completo al usuario. Este código se asegura de que esto ocurra, ya que es una gran try/catch todos sus servidores de solicitudes (servlets, acciones de struts o cualquier controlador ....)

try{ //run the code which handles user request. }catch(Throwable ex){ LOG.error("Exception was thrown: {}", ex); //redirect request to a error page. }

}

Como otro ejemplo, considere que tiene una clase de servicio que sirve negocios de transferencia de fondos. Este método devuelve un TransferReceipt si la transferencia se realiza o NULL si no puede.

String FoundtransferService.doTransfer( fundtransferVO);

Ahora, al obtener imágenes, obtiene una List de transferencias de fondos del usuario y debe usar el servicio anterior para hacerlas todas.

for(FundTransferVO fundTransferVO : fundTransferVOList){ FoundtransferService.doTransfer( foundtransferVO); }

¿Pero qué pasará si ocurre alguna excepción? No debe detenerse, ya que una transferencia puede haber sido exitosa y otra no, debe continuar pasando por toda la List usuarios y mostrar el resultado de cada transferencia. Entonces terminas con este código.

for(FundTransferVO fundTransferVO : fundTransferVOList){ FoundtransferService.doTransfer( foundtransferVO); }catch(Throwable ex){ LOG.error("The transfer for {} failed due the error {}", foundtransferVO, ex); } }

Puede navegar por muchos proyectos de código abierto para ver que el throwable está realmente en caché y manejado. Por ejemplo, aquí hay una búsqueda de tomcat , struts2 y struts2 :

https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable

¿Es una mala práctica atrapar a Throwable ?

Por ejemplo algo como esto:

try { // Some code } catch(Throwable e) { // handle the exception }

¿Es esta una mala práctica o deberíamos ser lo más específicos posible?


Catching Throwable a veces es necesario si está utilizando bibliotecas que arrojan errores con demasiado entusiasmo, de lo contrario, su biblioteca puede matar su aplicación.

Sin embargo, sería mejor en estas circunstancias especificar solo los errores específicos arrojados por la biblioteca, en lugar de todos los Throwables.


Debes ser lo más específico posible. De lo contrario, los errores imprevistos podrían escabullirse de esta manera.

Además, Throwable cubre el Error y generalmente no es un punto de retorno . No desea detectar / manejar eso, quiere que su programa muera inmediatamente para que pueda arreglarlo correctamente.


Esta es una mala idea. De hecho, incluso la captura de Exception suele ser una mala idea. Consideremos un ejemplo:

try { inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() ); } catch(Throwable e) { inputNumber = 10; //Default, user did not enter valid number }

Ahora, digamos que getUserInput () bloquea por un tiempo, y otro hilo detiene el hilo de la peor manera posible (llama a thread.stop ()). Tu bloque catch capturará un error ThreadDeath . Esto es súper malo. El comportamiento de su código después de atrapar esa excepción no está definido en gran medida.

Un problema similar ocurre con la captura de Excepción. Tal vez getUserInput() falló debido a una excepción de interrupción, o una excepción de permiso denegado al tratar de registrar los resultados, o todo tipo de otras fallas. No tiene idea de qué fue lo que salió mal, debido a eso, tampoco tiene idea de cómo solucionar el problema.

Tienes tres mejores opciones:

1 - Capture exactamente la (s) excepción (es) que sabe cómo manejar:

try { inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() ); } catch(ParseException e) { inputNumber = 10; //Default, user did not enter valid number }

2 - Retome cualquier excepción que encuentre y no sepa cómo manejarla:

try { doSomethingMysterious(); } catch(Exception e) { log.error("Oh man, something bad and mysterious happened",e); throw e; }

3 - Usa un bloque finally para que no tengas que recordar volver a lanzar:

Resources r = null; try { r = allocateSomeResources(); doSomething(r); } finally { if(r!=null) cleanUpResources(r); }


La pregunta es un poco vaga; ¿Estás preguntando "¿está bien atrapar Throwable ", o "¿está bien atrapar un Throwable y no hacer nada"? Mucha gente aquí respondió lo último, pero eso es un problema secundario; El 99% de las veces no debes "consumir" o descartar la excepción, ya sea que estés atrapando Throwable o IOException o lo que sea.

Si propaga la excepción, la respuesta (como la respuesta a tantas preguntas) es "depende". Depende de lo que haga con la excepción: por qué lo está atrapando.

Un buen ejemplo de por qué quieres atrapar a Throwable es proporcionar algún tipo de limpieza si hay algún error. Por ejemplo, en JDBC, si se produce un error durante una transacción, le conviene deshacer la transacción:

try { … } catch(final Throwable throwable) { connection.rollback(); throw throwable; }

Tenga en cuenta que la excepción no se descarta, sino que se propaga.

Pero como política general, atrapar a Throwable porque no tienes un motivo y eres demasiado flojo para ver qué excepciones están pasando es de mala forma y una mala idea.


No es una mala práctica si no puedes tener una burbuja de excepción de un método.

Es una mala práctica si realmente no puede manejar la excepción. Es mejor agregar "tiradas" a la firma del método que simplemente atrapar y volver a lanzar o, lo que es peor, envolverlo en una RuntimeException y volver a lanzar.


Si bien en general es una mala práctica atrapar a Throwable (como lo aclararon las numerosas respuestas sobre esta pregunta), los escenarios donde capturar a Throwable son útiles son bastante comunes. Permítanme explicar uno de esos casos que uso en mi trabajo, con un ejemplo simplificado.

Considere un método que realiza la adición de dos números, y después de la adición exitosa, envía una alerta por correo electrónico a ciertas personas. Supongamos que el número devuelto es importante y lo utiliza el método de llamada.

public Integer addNumbers(Integer a, Integer b) { Integer c = a + b; //This will throw a NullPointerException if either //a or b are set to a null value by the //calling method successfulAdditionAlert(c); return c; } private void successfulAdditionAlert(Integer c) { try { //Code here to read configurations and send email alerts. } catch (Throwable e) { //Code to log any exception that occurs during email dispatch } }

El código para enviar alertas por correo electrónico lee muchas configuraciones del sistema y, por lo tanto, puede haber una variedad de excepciones lanzadas desde ese bloque de código. Pero no queremos que ninguna excepción encontrada durante el envío de alertas se propague al método de llamador, ya que ese método simplemente se refiere a la suma de los dos valores de Entero que proporciona. Por lo tanto, el código para enviar alertas por correo electrónico se coloca en un bloque try-catch , donde Throwable es capturado y cualquier excepción simplemente se registra, permitiendo que el resto del flujo continúe.


Si utilizamos throwable , también cubre Error y eso es todo.

Ejemplo.

public class ExceptionTest { /** * @param args */ public static void m1() { int i = 10; int j = 0; try { int k = i / j; System.out.println(k); } catch (Throwable th) { th.printStackTrace(); } } public static void main(String[] args) { m1(); }

}

Salida:

java.lang.ArithmeticException: / by zero at com.infy.test.ExceptionTest.m1(ExceptionTest.java:12) at com.infy.test.ExceptionTest.main(ExceptionTest.java:25)


También tenga en cuenta que cuando atrapa Throwable , también puede detectar InterruptedException que requiere un tratamiento especial. Consulte Cómo abordar la excepción interrumpida para obtener más detalles.

Si solo desea capturar excepciones no verificadas, también podría considerar este patrón

try { ... } catch (RuntimeException exception) { //do something } catch (Error error) { //do something }

De esta forma, cuando modifique su código y agregue una llamada a método que pueda generar una excepción marcada, el compilador se lo recordará y luego podrá decidir qué hacer para este caso.


Throwable es la clase base para todas las clases que puede arrojarse (no solo excepciones). Es poco lo que puede hacer si detecta un OutOfMemoryError o KernelError (consulte cuándo atrapar java.lang.Error? )

capturar excepciones debería ser suficiente.


Throwable es la superclase de todos los errores y excedentes. Si usa Throwable en una cláusula catch, no solo capturará todas las excepciones, sino que también detectará todos los errores. La JVM produce errores para indicar problemas graves que no están destinados a ser manejados por una aplicación. Ejemplos típicos para eso son OutOfMemoryError o Error. Ambos son causados ​​por situaciones que están fuera del control de la aplicación y no se pueden manejar. Por lo tanto, no deberías atrapar objetos Throwables a menos que tengas la plena seguridad de que solo será una excepción dentro de Throwable.


depende de tu lógica o de ser más específico para tus opciones / posibilidades. Si hay alguna excepción específica sobre la que pueda reaccionar de forma significativa, podría atraparla primero y hacerlo.

Si no lo hay y está seguro de que hará lo mismo con todas las excepciones y errores (por ejemplo, salir con un mensaje de error), entonces no es problema atrapar el objeto arrojado.

Por lo general, el primer caso se cumple y no se detectaría el lanzamiento. Pero todavía hay muchos casos en los que la captura funciona bien.


directamente desde el javadoc de la clase Error (que recomienda no detectar estos):

* An <code>Error</code> is a subclass of <code>Throwable</code> * that indicates serious problems that a reasonable application * should not try to catch. Most such errors are abnormal conditions. * The <code>ThreadDeath</code> error, though a "normal" condition, * is also a subclass of <code>Error</code> because most applications * should not try to catch it. * A method is not required to declare in its <code>throws</code> * clause any subclasses of <code>Error</code> that might be thrown * during the execution of the method but not caught, since these * errors are abnormal conditions that should never occur. * * @author Frank Yellin * @version %I%, %G% * @see java.lang.ThreadDeath * @since JDK1.0