Pregunta

Es una mala práctica para la captura de 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 tan específico como sea posible?

¿Fue útil?

Solución

Usted necesita ser tan específico como sea posible.Imprevistos insectos podrían aleje un poco de esta manera.

Además, Throwable cubre Error así y eso es generalmente no hay punto de retorno.No quieres coger el mango de eso, usted quiere que su programa para morir inmediatamente, de modo que usted puede arreglar correctamente.

Otros consejos

Esto es una mala idea.De hecho, incluso la captura de Exception es generalmente una mala idea.Veamos un ejemplo:

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

Ahora, digamos que getUserInput() se bloquea por un tiempo, y otro hilo se detiene el hilo de la peor manera posible ( se llama hilo.stop() ).Su bloque catch se captura un ThreadDeath Error.Esto es super malo.El comportamiento de su código después de la captura de esa Excepción es en gran medida indefinido.

Un problema similar ocurre con la captura de la Excepción.Tal vez getUserInput() error debido a un InterruptException, o niega el permiso de excepción al intentar registrar los resultados, o todo otro tipo de fallas.Usted no tiene idea de lo que salió mal, como a causa de eso, usted también no tiene idea de cómo solucionar el problema.

Usted tiene tres opciones:

1-que Capturar exactamente la Excepción(s) que usted sabe cómo manejar:

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

2 -- Rethrow cualquier excepción que correr y no saben cómo manejar:

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

3-con el Uso de un bloque finally así que usted no tiene que recordar para volver a iniciar:

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

También ser conscientes de que cuando se captura Throwable, también se puede coger InterruptedException lo que requiere de un tratamiento especial.Ver Tratar con InterruptedException para obtener más detalles.

Si usted sólo quiere coger sin marcar excepciones, usted también podría considerar la posibilidad de que este patrón

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

De esta manera, al modificar el código y añadir una llamada al método que puede lanzar una excepción comprobada, el compilador le recordará que en y, a continuación, usted puede decidir qué hacer para este caso.

directamente desde el javadoc de la clase de Error (en la que se recomienda no a la captura de 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

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

Es una mala práctica, si usted realmente no puede manejar la excepción.Mejor añadir "tira" a la firma del método que capturar y volver a producir o, lo que es peor, se envuelve en una RuntimeException y volver a tirar.

La captura de Arrojar a veces es necesario si usted está usando las bibliotecas que tirar Errores de sobre-entusiasmo, de lo contrario su biblioteca, puede matar a su aplicación.

Sin embargo, sería mejor bajo estas circunstancias, para especificar sólo los errores generados por la biblioteca, en lugar de todos los Throwables.

Arrojadiza es la clase base para todas las clases que pueden ser lanzadas (no sólo las excepciones).Poco se puede hacer si usted coge un OutOfMemoryError o KernelError (ver Cuando para la captura de java.lang.Error?)

captura de Excepciones debe ser suficiente.

depende de la lógica o, para ser más específicos para sus opciones / posibilidades.Si hay alguna excepción específica que usted posiblemente puede reaccionar en una manera significativa, se podría tomar el primero y hacerlo.

Si no estás seguro de que va a hacer lo mismo para todas las excepciones y errores (por ejemplo salir con un mensaje de error), que no es problema para coger el arrojadiza.

Generalmente el primer caso se tiene y que no captura la arrojadiza.Pero todavía hay un montón de casos donde la captura funciona bien.

Aunque se describe como una muy mala práctica, a veces se puede encontrar raras los casos que no sólo es útil sino también obligatoria.Aquí hay dos ejemplos.

En una aplicación web donde se debe mostrar un significado completo de la página de error al usuario.Este código de asegurarse de que esto ocurra, ya que es una gran try/catch alrededor de todo su solicitud handelers ( servlets, struts acciones, o de 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 la posibilidad de tener una clase de servicio que sirve de transferencia de fondos del negocio.Este método devuelve un TransferReceipt si la transferencia se hace o NULL si no.

String FoundtransferService.doTransfer( fundtransferVO);

Ahora imágenes de obtener una List de transferencias de fondos de usuario y usted debe utilizar el servicio para hacerlas todas.

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

Pero, ¿qué pasaría si cualquier la excepción ocurre?Usted no debe parar, como una transferencia de mayo han sido éxito y no se puede, usted debe mantener a ir a través de todos los usuario List, y mostrar el resultado de cada transferencia.Así se termina 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);
  }
}

Usted puede navegar por un montón de proyectos de código abierto para ver que el throwable es realmente en caché y se maneja.Por ejemplo, aquí está una búsqueda de tomcat,struts2 y primefaces:

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

La pregunta es un poco ambigua;está usted preguntando "¿está bien para coger Throwable"o "¿está bien coger un Throwable y no hacer nada"?Muchas personas aquí contestado a la última, pero eso es un asunto secundario;El 99% del tiempo no debe "consumir" o descartar la excepción, ya que son la captura de Throwable o IOException o lo que sea.

Si usted propagar la excepción, la respuesta (como la respuesta a tantas preguntas) es "depende".Depende de lo que estés haciendo con la excepción—¿por qué estás atrapa.

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

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

Tenga en cuenta que la excepción no se descarta, pero que se propagan.

Pero como política general, la captura de Throwable porque usted no tiene una razón y son demasiado perezosos para ver qué excepciones específicas que están siendo lanzados es la falta de forma y una mala idea.

Generalmente hablando, usted quiere evitar la captura de Errors pero no puedo pensar en (al menos) dos casos específicos en los que es apropiado hacerlo:

  • Desea cerrar la aplicación en respuesta a errores, especialmente AssertionError que es inofensivas.
  • Se está implementando un hilo de un mecanismo de agrupación similar a la ExecutorService.submit() que requiere que usted envíe excepciones de vuelta al usuario, por lo que puede manejar.

Si utilizamos arrojadiza, luego se cubre Error así 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)

Arrojadiza es la superclase de todos los errores y excetions.Si utiliza Arrojadiza en un retén de la cláusula, no sólo capturar todas las excepciones, que también se captura todos los errores.Los errores se producen por la JVM para indicar problemas graves que no están destinados a ser manipulados por una aplicación.Ejemplos típicos de ello son los OutOfMemoryError o la StackOverflowError.Ambas son causadas por situaciones que están fuera del control de la aplicación y no pueden ser manejados.Así que no se debe coger Throwables a menos que usted está bastante seguro de que sólo será una excepción residen en el interior Arrojadiza.

Mientras que es generalmente mala práctica detectar Arrojadiza (como determinadas por las numerosas respuestas en esta pregunta), los escenarios donde la captura de Throwable es útil son bastante comunes.Permítanme explicar un caso que yo uso en mi trabajo, con un ejemplo simplificado.

Considere la posibilidad de un método que realiza la suma de dos números, y después de una exitosa además, se envía una alerta de correo electrónico para ciertas personas.Supongamos que el número devuelto es importante y utilizado por 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 de correo electrónico que lee mucho de las configuraciones del sistema y, por lo tanto, podría haber una variedad de excepciones desde el bloque de código.Pero no queremos que cualquier excepción encontrados durante la alerta de envío se propaguen a la persona que llama método, ya que el método es simplemente cuestión con la suma de los dos valores Enteros que proporciona.Por lo tanto, el código para el envío de alertas de correo electrónico que se coloca en un try-catch cuadra, donde Throwable es capturado y las excepciones son simplemente registra, permitiendo que el resto del caudal para continuar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top