2009-01-31 13 views
37

Dado: Throwable es la superclase de Exception.¿Cuándo se debe usar Throwable en lugar de Excepción nueva?

Cuando leo textos sobre cómo escribir sus propias 'excepciones', veo ejemplos de Throwable siendo utilizados en el bloque catch y otros textos muestran new Exception() que se utiliza en el bloque catch. Todavía tengo que ver una explicación de cuándo uno debería usar cada uno.

Mi pregunta es la siguiente, ¿cuándo se debe usar Throwable y cuándo se debe usar new Exception()?

EDIT: Dentro del bloque catch o else utilizando:

throw throwable; 

o

throw new Exception(); 
+1

¿Por qué usan "nuevo"? ¿Estás comparando captura (Throwable) vs catch (Exception)? –

+0

@WolfmanDragon: ¿Estás lanzando Throwable/Exception desde * inside * the catch block? ¿Debemos suponer que "arrojable" es un lanzador existente atrapado por ese bloque? –

+0

@Zach Scrivena: no, esta fue una pregunta general. He escrito excepciones en C++ pero nunca en Java, y estoy un poco confundido. El problema que planteó esto es que necesito pasar una 'excepción' a un código que un compañero de trabajo está creando si no se genera una colección. – WolfmanDragon

Respuesta

11

(de comentarios) El tema que trajo esto es que Necesito pasar una 'excepción' a un fragmento de código de un compañero de trabajo es la construcción de una colección si no consigue construido .

En ese caso, es posible que desee lanzar una excepción marcada. Puede lanzar Exception, una subclase correspondiente adecuada (excepto RuntimeException y sus subclases que son sin marcar) o una subclase personalizada de Exception (por ejemplo, "CollectionBuildException"). Consulte Java Tutorial on Exceptions para ponerse al día con las excepciones de Java.

+0

Si bien su respuesta responde a mi comentario, todavía no entiendo por qué algunos de los grandes nombres del campo dicen tirar Throwable (Hardcore Java Por Robert Simmons, Jr.) mientras que otros dicen nunca usar Throwable. Hardcore Java resulta ser el mejor libro de java de todos los tiempos, excepto en este caso. – WolfmanDragon

+3

Throwable es la superclase de Exception and Error. De las tres clases, consideraría que Exception es la más adecuada para la tarea. La mayoría de las personas escribe bloques try-catch que solo tienen en cuenta la excepción y sus subclases; no podrán manejar un nuevo Throwable(). –

+0

(cont.) A menos que haya una "captura (Throwable t)" también. –

32

tirar siempre una excepción (nunca un Throwable). Generalmente no atrapas a Throwable tampoco, pero puedes. Throwable es la superclase de Exception and Error, por lo que verás Throwable si no solo quieres capturar excepciones, sino también errores, ese es el sentido de tenerla. La cuestión es que los errores generalmente son cosas que una aplicación normal no debería capturar, así que simplemente use Exception a menos que tenga una razón específica para usar Throwable.

+6

No arroje una excepción, eche la subclase Exception apropiada o la suya propia. El objetivo de la excepción que tiene sub clases es que diferentes tipos de problemas pueden tener sus propias excepciones. Además de incluir el mensaje y posiblemente envolver la excepción de causa, se pueden agregar "datos" adicionales. –

+0

Sí, eso es lo que quise decir, lanzar una subclase de Excepción. Lo siento no estaba pensando lo suficiente. –

+1

esta es la respuesta correcta. el asker ha hecho una desafortunada elección para cuál marcar correctamente. también vea el comentario de cHao en una respuesta diferente arriba que complementa muy bien esta. – necromancer

1

Throwable es una interfaz, no una clase. Dos clases extienden Throwable, Exception y Error.

La regla es: sea lo más específico posible cuando capture excepciones; eso significa, por ejemplo, capturar excepciones en lugar de Throwable, e IOException en lugar de Exception.

No captar errores: los errores son errores. Corrige el código en su lugar.

Si tiene que atrapar absolutamente todo, use "atrapar Throwable", pero esta es una mala forma.

+0

Throwable también es una clase de hormigón. –

+0

Oye, en realidad había tenido la impresión de que Throwable era una interfaz hasta que lo busqué. No estoy seguro de por qué es esto o si esto es algo nuevo. –

+0

Gracias por señalar eso. Supongo que el sufijo -able me indujo a error. –

7

No debería captar una excepción y lanzar una nueva tan general como "nueva excepción".

En cambio, si desea propagarse por la excepción que acaba de hacer lo siguiente:

try { 
    // Do some stuff here 
} 
catch (DivideByZeroException e) { 
    System.out.println("Can't divide by Zero!"); 
} 
catch (IndexOutOfRangeException e) { 
    // catch the exception 
    System.out.println("No matching element found."); 
} 
catch (Throwable e) { 
    throw e; // rethrow the exception/error that occurred 
} 

no es una buena práctica, creo, para detectar una excepción y lanzar una nueva excepción en lugar de la que estaba elevado a su bloque de código, a menos que genere una excepción personalizada útil que proporcione suficiente contexto para eludir la causa de la excepción original.

+0

Su código no es Java. – starblue

+2

Este código descartaría las excepciones DivideByZero e IndexOutOfRange. Iniciar sesión en la excepción antes de lanzarla generalmente es una mala idea. Si se registra una excepción, generalmente es mejor hacerlo en el nivel de la pila que es responsable de manejar realmente el error, sin volver a lanzar. – erickson

+2

El código está destinado a abordar la pregunta del interrogador. Las mejores prácticas que no afectan la pregunta del interrogador están fuera del alcance de esta respuesta. Solo quiero mostrarle que puede abordar casos de excepción pero aún puede volver a lanzar la excepción si se ha producido una excepción excepcional. – MichaelD

0

Como lo escuché cuando salió Java por primera vez, la teoría era que Throwable podría usarse para la transferencia de control en otros casos además de las excepciones. Nunca lo había visto usado de esa manera (y eso es probablemente una muy buena cosa).

Así que solo atrapa Exception (o mejor aún, una excepción más refinada).

0

Throwable está destinado a ser capturado solo por el contenedor o el bucle principal de su programa. La mayoría de las veces, detectar cosas debajo de Exception, por ejemplo, Error, no agrega mucha capacidad a un programa, después de todo, ¿qué se puede hacer si se lanzan otros errores de VirtualError? No mucho, excepto registrar y continuar.

+0

Entonces, ¿puedes usar throwable si se va a pasar al main o servlet para tomar una decisión lógica? nueva Exception() si solo se va a registrar? – WolfmanDragon

1

throw new Exception(); es algo que debe Nunca hacer en un bloque catch, pero puede que tenga que o quiere hacer un tiro new SomeException(throwable); (preservación de la traza completa) en lugar de throw throwable; con el fin de ajustarse a la API de su método, p.ej cuando declara lanzar SomeException pero está llamando al código que podría arrojar un IOException que no desea agregar a la cláusula throws de su método.

El caso probablemente más común es new RuntimeException(throwable); para evitar tener una cláusula throws por completo. Mucha gente te dirá que es un abuso horrible porque deberías estar usando excepciones marcadas. OMI están equivocados y las excepciones comprobadas son un error en el diseño del lenguaje Java que solo da como resultado un código feo e inmanejable.

+1

La excepción no comprobada es una causa común de "abstracciones con fugas". http://www.joelonsoftware.com/articles/LeakyAbstractions.html Están bien para informes de error de talla única, útiles en muchos casos, pero no pueden admitir el verdadero manejo de excepciones frente a la abstracción . – erickson

0

Todas las excepciones son un problema al final ... también dicen que los errores son errores no significan nada.

Los errores no son errores: son problemas que experimenta la máquina virtual anfitriona, por ejemplo, OutOfMemoryError. Las excepciones son un medio que la operación actual puede utilizar para notificar que falló y tal vez proporcionar algún diagnóstico.

0

En general, no arrojaría ni atraparía a Throwable. En particular, los errores de JVM (que extienden el Error()) no son significaron para ser capturados por el código de usuario a menos que esté haciendo un trabajo de nivel de sistema extraño.

Tratar "Throwable" como un artefacto de lenguaje. La clase "Excepción" se llama así porque es la que está destinada a ser utilizada por los programadores cuando quieren que un bloque de código salga "excepcionalmente", al no salir normalmente o devolver un valor.

Esto incluye tanto situaciones de error regulares (por errores "regulares" me refiero a JVM) como lugares donde está utilizando excepciones como mecanismo de control.

0

No use excepciones como un "tipo de retorno" o bien ...

Si la condición que está lanzando para es común, que está gastando una enorme cantidad de recursos para devolver esa condición a la que llama rutina. Las excepciones son caras de construir.

He visto casos en los que los lazos cerrados arrojaban excepciones como "negativas", por ejemplo, La asignación de ID, esta rutina ocupaba aproximadamente el 99% del tiempo de la CPU. Cuando se cambiaba a una constante de retorno documentada, esta disminuía al 25%.

5

sólo dos lugares que usted debe ver la palabra Throwable en código:

public static void main(String args[]) 
{ 
    try 
    { 
     // Do some stuff 
    } 
    catch(Throwable t) 
    { 

    } 
} 

Y

public class SomeServlet extends HttpServlet 
{ 
     public void doPost(HttpRequest request, HttpResponse response) 
     { 
     try 
     { 
      // Do some stuff 
     } 
     catch (Throwable t) 
     { 
       // Log 
     } 
     } 
} 
+5

Incluso estos dos serían al menos uno demasiados, IMO. Capturar 'Throwable' (especialmente fuera de 'main') es una receta para el desastre, ya que estás lanzando una red demasiado amplia. Más que solo excepciones de nivel de aplicación son Throwable. Ejemplo común: Errores OOM. ¿Cómo va a iniciar sesión si el hecho de escribir un registro hace que se cree un objeto (leído: asignado, por el mismo proceso que simplemente falló)? Y cuando eso * no *, ¿qué ocurre ahora? Perdió la información que causó el error original, porque ha causado una nueva que se propagará en su lugar. Eso es si la aplicación no acaba de morir. – cHao

Cuestiones relacionadas