2012-09-24 29 views
24

En el pasado había leído toneladas de código con métodos como:"tiros Throwable" buenas prácticas

public Object doSomething() throws Throwable { 
    ... 
} 

¿Es una práctica común para hacer eso?

¿Qué son los pros & cons?

¿No es mejor que catch y printStackTrace()?

throws Trowable parecía a mí como la forma "agente naranja" de conseguir la materia hecho excepcionalmente

EDITAR

excepciones
  1. Handle esperado en el Método

  2. Lanzar unexpectet (uno por uno)

  3. me importa no programática de un error

Es que el camino a seguir?

+1

probablemente esto le dará una explicación: http://stackoverflow.com/questions/498217/when-should-throwable-be-used-instead-of-new-exception – Serge

+0

"throws Throwable" es más comúnmente utilizado en SDKs y definiciones de framework. Aquí hay un ejemplo en el marco de prueba de Android donde lo usan: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/android/test/ InstrumentationTestCase.java # InstrumentationTestCase –

Respuesta

42

No debe arrojar Throwable. Este es el por qué.

Throwable es la parte superior de la jerarquía de cosas que se pueden lanzar y se compone de Exceptions y Errors. Como el Errors, por definición, surge de condiciones no saldables, no tiene sentido incluirlas en su declaración de método. Eso deja solo Exception.

En su lugar, debe declarar su método con throws Exception.


Tenga en cuenta que cuanto más estrecho sea el rango de throws, mejor.

Declarar que su método es throws Exception está bien si su método no genera las excepciones, sino que llama a otro código que se declara como throws Exception y desea excepciones para filtrar la pila de llamadas.

Si su método es la generación de la excepción, entonces declarar un rango más estrecho, por ejemplo throws IOException, MyProcessingException, etc

+2

. Añadiría que si las excepciones que está filtrando pueden corregirse a través del código en algún momento de la cadena, entonces está bien declarar arroja Exception(), pero si no es algo que el código utilizará para repararse a sí mismo, entonces debería capturar las excepciones y volver a lanzarlas como RuntimeExceptions. En ese caso, no declara en su método que arroja una Excepción de tiempo de ejecución, documenta que lo hace con javadoc. –

1

Funcionalmente, es equivalente con throws Exception, ya que los errores están desmarcados.

No veo ninguna razón para declarar un método para tirar Throwable. Sin embargo, esto no significa que catch e printStackTrace sean una buena alternativa.

Por lo general, desea capturar objetos desechables donde puede hacer algo sensato con ellos.

Código que arroja un objeto arrojado que no espera que explote gloriosamente, por lo que puede ver el error y corregir el error.

+2

Puede lanzar una subclase de Throwable que no sea una excepción o un error, pero esto no es aconsejable. ;) –

+0

Correcto, por supuesto. Realmente espero que esto no importe en la práctica. – Buhb

+1

Las subclases de Throwable se verifican como Throwable (excepto para las subclases de Error y RuntimeException) –

0

¿Estás preguntando sobre Throwable específicamente? Si es así, entonces no es una buena práctica. No proporciona ninguna información útil al usuario de la clase (método).

1

¿Es una práctica común hacer eso?

En el JDK es raro. Esto se usa principalmente cuando no está claro cómo manejar las excepciones marcadas.

¿Qué son los pros & cons?

Los pros es que usted obtenga su código para compilar sin preocuparse por exception.s controladas

Las desventajas es que la excepción debe ser el manejo están siendo ignorados.

¿No es mejor capturar e imprimirStackTrace()?

La excepción no controlada se suele imprimir de todas formas, por lo que su captura no ayuda mucho.

Debería detectar una excepción cuando puede agregar algún valor al hacerlo y agregar la excepción a la cláusula throws cuando no pueda.

8

Esa es una pregunta cargada. Esto no se trata tanto del manejo de excepciones como de la legibilidad del código.

Depende de dónde obtenga sus muestras de código. Los profesionales prefieren ser más específicos al tirar un método. La razón principal es que mantiene sus API más legibles. Por ejemplo, si tu método arroja Throwable, eso básicamente significa que cualquier cosa podría pasar y tu método no quiere lidiar con eso, sin importar qué. Pero, en realidad, sólo un número limitado de cosas puede suceder:

  • Cualquiera que sea verificado excepciones resultantes de otras llamadas que están haciendo en su método
  • Cualquiera que sea verificado excepciones usted está lanzando a propósito en función de sus propias afirmaciones
  • Cualquiera que sea excepción no comprobada que no planeó para
  • errores (java.lang.Error) que son más global a la JVM y el medio ambiente

por sta concreto Si desea agregar las excepciones que desea lanzar, le está diciendo a los usuarios de su API acerca de qué deben tener en cuenta. Por ejemplo, cuando usa InputStream, notará que la mayoría de los métodos arrojan al menos java.io.IOException, que le brinda información útil sobre lo que debe observar.

Al codificar, como norma general, debe intentar mantener sus API lo más expresivas posible. Básicamente, tiene una línea de código para mostrar la API pública de un método (es decir, su firma, las anotaciones también, supongo), por lo que la quiere completamente expresiva (tipo de devolución, nombre, parámetros, pero también las excepciones arrojadas).

En cuanto a atrapar los throwables e imprimir el seguimiento de la pila, diría que no debería detectar la excepción a menos que pueda hacer algo al respecto.En cambio, deje que suba la pila de llamadas hasta que alguna clase lo atrape y haga algo al respecto. A veces, puede rodar hasta su clase principal, lo que supongo que tendría que atraparlo e imprimir el seguimiento de la pila como último recurso. Básicamente, si no puedes actuar sobre la excepción, entonces deja que suba la pila de llamadas. Además, es extremadamente raro que se encuentre en una situación en la que debe silenciar una excepción (es decir, atraparla pero no hacer nada al respecto). Eso suele provocar problemas cuando llega el momento de solucionar problemas.

Aquí hay un article divertido pero interesante sobre el mal uso del manejo de excepciones en general.

1

Es una cuestión verdaderamente discutible. Tener el método arrojando demasiadas excepciones dará como resultado una gran cantidad de código de manejo de errores. Algunas veces no es intencional.

Pero porque no me gusta demasiadas excepciones en la firma no significa que vamos a utilizar Parent de todas las excepciones y ¡¡¡ya terminamos !! No funcionará.

Lo que uno puede hacer es categorizar excepciones tales como BusinessException, ServiceException de modo que si usted tiene una regla de negocio que dice que minimum balance in account can not be less than say 100$ continuación InsufficientBalance excepción será generado que será niño de BusinessException

por lo que el método será como

public Object doSomething() throws BusinessException { 

if(!hasMinimumbalance()) 
    { 
    throw new InsufficientBalance(ErrorCode); 
    } 
} 

lo que esto hará es excepciones relacionados con el club juntos y cada vez que el usuario quiere API para detectar la excepción de error específico, entonces él puede hacerlo, el manejo de errores genéricos más es posible.

El punto central aquí es en la interfaz de usuario se debe mostrar al usuario que Se ha quedado fuera de equilibrio y no se puede retirar dinero

Se puede decir en el aspecto más amplio para mostrar formato legible por humanos de error, es realmente necesario tener separación de excepciones.

0

Tirar (y atrapar) Throwable (o Exception) es generalmente una mala práctica porque 'cubre' cualquier excepción específica que pueda querer atrapar. A continuación, tendría que recurrir a la fealdad, como a continuación:

public void myMethod() throws Throwable { 
    if (x) { 
     throw new MyException1(); 
    } 
    if (y) { 
     throw new MyException2(); 
    } 
} 

public void callingMethod() { 
    try { 
     myMethod(); 
    } 
    catch(Throwable t) { 
     if (t instanceof MyException1) { 
      // handle exception 1 
     } 
     else if (t instanceof MyException2) { 
      // handle exception 2 
     } 
     else { 
      // handle other exceptions 
     } 
    } 
} 

Cuál es propenso a errores (y lo ha marcado la CheckStyle como una violación del código). Es mucho más preferible tener un código como éste:

public void myMethod() throws MyException1, MyException2 { 
    if (x) { 
     throw new MyException1(); 
    } 
    if (y) { 
     throw new MyException2(); 
    } 
} 

public void callingMethod() { 
    try { 
     myMethod(); 
    } 
    catch(MyException1 e) { 
     // handle exception 1 
    } 
    catch(MyException2 e) { 
     // handle exception 2 
    } 
} 

Manejo de una excepción con sólo llamar printStackTrace() por lo general no es una buena idea. printStackTrace() envía el stacktrace al error estándar, que puede no leerse en absoluto. Una mejor opción es usar el recurso de registro de la aplicación (como log4j) para informar la excepción. Incluso entonces, simplemente iniciar sesión podría no ser suficiente.

Mi regla de oro es:

Si usted puede manejar una excepción a nivel local, que lo hagan. Por ejemplo, cuando analizar una cadena como un entero se puede coger el NumberFormatException y devolver un valor por defecto:

prvate int parseAmount(String amountValue) { 
    int amount; 
    try { 
     amount = Integer.parseInt(amountValue); 
    } 
    catch(NumberFormatException e) { 
     // default amount 
     amount = 0; 
    } 
    return amount; 
} 

Si usted no puede manejar una excepción a nivel local, considere si debe exponer el tipo de excepción que está siendo lanzada.Si este tipo es algún tipo (dependiente de la implementación) oscura, a continuación, envolviéndolo en su propio tipo de excepción genérica es probablemente una buena idea:

private Customer getCustomer(int customerId) throws ServiceException { 
    try { 
     return customerService.getCustomer(customerId); 
    } 
    catch(CustomerServiceSpaghettiTangledException e) { 
     throw new ServiceException("Error calling the customer service", e); 
    } 
} 

Aquí 'ServiceException' es una subclase de excepción creada por ti. Spring también ofrece un exception hierarchy específicamente para este propósito.

Al incluir la excepción, oculta los detalles de implementación, haciendo que su capa de servicio sea mucho más simple de usar.

Si decide lanzar una excepción de su método, tendrá que manejarlo 'más arriba' en la pila de llamadas. Esta puede ser una página de error genérico en su aplicación web que indica que algo salió mal y posiblemente proporciona un mensaje de error o código. En algunos casos, el código de nivel superior puede intentar un reintento o posiblemente una forma alternativa de obtener el resultado requerido.

1

En algunos casos raros, es aceptable tirar Throwable s. Por ejemplo, @Around consejos en Spring AOP generalmente se declaran para arrojar un Throwable.

En el siguiente ejemplo se copia textualmente de Spring AOP docs:

import org.aspectj.lang.annotation.Aspect; 
    import org.aspectj.lang.annotation.Around; 
    import org.aspectj.lang.ProceedingJoinPoint; 

    @Aspect 
    public class AroundExample { 

     @Around("com.xyz.myapp.SystemArchitecture.businessService()") 
     public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { 
      // start stopwatch 
      Object retVal = pjp.proceed(); 
      // stop stopwatch 
      return retVal; 
     } 

    } 

¿Por qué es doBasicProfiling declaró a lanzar una Throwable? Debido a que el método original (es decir, el punto de unión de ejecución), podría arrojar un Error, RuntimeException, o una excepción marcada. Por lo tanto, tiene sentido declarar doBasicProfiling para arrojar un Throwable.

Cuestiones relacionadas