2010-07-08 11 views
59

¿Cuál es la regla general a la hora de decidir si agregar una cláusula throws a un método o utilizar un try-catch?Lanza o prueba + captura

Por lo que he leído, los lanzamientos deben usarse cuando la persona que llama ha roto su parte del contrato (objeto pasado) y el try-catch debe usarse cuando se produce una excepción durante una operación que se está realizando llevado a cabo dentro del método. ¿Es esto correcto? Si es así, ¿qué debería hacerse por el lado de las personas que llaman?

P.S: Se ha buscado a través de Google y SO, pero me gustaría tener una respuesta clara en este caso.

+3

Siempre he sido fanático de "Si tiene sentido tratar con esto aquí ... entonces hágalo". – CheesePls

+0

Me gustaría que todas mis excepciones se solucionen donde ocurren, así no tengo que lidiar con el futuro. –

Respuesta

43
  • capturar una excepción sólo si se puede manejar de una manera significativa
  • declarar que lanza la excepción al alza si se va a ser manejado por el consumidor del método actual
  • excepciones tiro si están causados ​​por los parámetros de entrada (pero estos son más a menudo sin control)
+0

Correcto, la tercera regla es muy clara. Acerca de manejar una excepción de una manera significativa, ¿está esto en las capas superiores de un programa? ¿Esto significa que las API generalmente arrojan Excepciones? Además, ¿en qué casos debería un método volver a lanzar excepciones provenientes de submétodos (provenientes de métodos privados de utilidad, por ejemplo)? –

+0

bueno, depende en gran medida. Las API arrojan excepciones, sí. Pero luego viene la opción de comprobado vs desmarcado. – Bozho

+3

¿Por qué volver a lanzar la excepción? Simplemente no lo atrape y páselo por la pila de llamadas. –

12

En general, un método debe lanzar una excepción a su llamador cuando no puede manejar el problema asociado localmente. P.ej. si se supone que el método debe leerse desde un archivo con la ruta especificada, IOExceptions no se puede gestionar localmente de forma sensata. Lo mismo se aplica a las entradas no válidas, agregando que mi elección personal sería lanzar una excepción sin marcar como IllegalArgumentException en este caso.

Y debe coger una excepción a un método llamado si

  • es algo que puede ser manejado a nivel local (por ejemplo, tratar de convertir una cadena de entrada a un número, y si falla la conversión, es completamente válido para devolver un valor predeterminado),
  • o no debe lanzarse (por ejemplo, si la excepción proviene de una capa inferior específica de la implementación, cuyos detalles de implementación no deberían ser visibles para quien llama - por ejemplo, no lo hago) Quiero mostrar que mi DAO usa Hibernate para persistir en mis entidades, por lo que capturo todas las HibernateExceptions localmente y las convierto en mis propios tipos de excepciones.
+0

Ok. Para reformular, se lanzaría una excepción cuando no sea posible una solución inmediata y se necesite alguna interacción "por encima" para decidir qué hacer. Además, una excepción no se volvería a lanzar si solo tiene un "significado" entre un grupo de clases y se debe lanzar una excepción más generalizada en su lugar para informar a la persona que llama que se necesita atención. ¿Suena más o menos bien? –

+1

@James, más o menos :-) Si por "interacción" te refieres a pedir intervención del usuario, no siempre es necesario. Además, en lugar de "más generalizado", preferiría "diferente". Una ConnectionException definida por el usuario no es más general que HibernateException. –

8

Mi regla de oro para personnal que es simple:

  • ¿Puedo manejarlo de una manera significativa (agregado del comentario)? Así que ponga el código en try/catch. Al manejarlo, me refiero a poder informar al usuario/recuperar del error o, en un sentido más amplio, ser capaz de entender cómo esta excepción afecta la ejecución de mi código.
  • Por otra parte, tirar a la basura

Nota: este replys ahora es un wiki de la comunidad, no dude en añadir más información en

+6

¿Puedo manejarlo * de una manera significativa *. – Nivas

+2

¿Cuáles son sus criterios para decidir si puede manejar una excepción localmente? ¿Está esto en el nivel en el que realmente puede encargarse de la excepción y mostrar un mensaje, por ejemplo? –

+0

Tirarlo es una mala idea. Mejor es pasarlo por la pila de llamadas. –

2

Si el método en el que consiguió produce la excepción tiene una cantidad sufficent de la información. para enfrentarlo, debería capturar, generar información útil sobre lo que sucedió y qué datos se estaban procesando.

+0

¿Siempre escribe la excepción de error en un archivo de registro o en la consola? Estaba pensando en esto anoche porque en el programa real no podrás ver la consola real, así que tus errores no deberían ir a un archivo de texto. Entonces, ¿cómo se imprime e.printStackTrace()? Voy a la consola cuando estoy depurando pero ¿a qué otra cosa podría ir? –

6

Aquí es la forma en que lo uso:

Lanza:

  • Lo que desea el código para detener cuando se produce un error.
  • Bueno con los métodos que son propensos a errores si se no cumplen ciertos requisitos previos.

Try-Catch:

  • Cuando usted quiere tener el programa comportarse de manera diferente con diferentes errores.
  • Genial si quieres proporcionar significativos errores a los usuarios finales.

Conozco a mucha gente que siempre usa Throws porque es más limpio, pero no hay tanto control.

+0

Casi NUNCA debe usar el manejo de excepciones para el control del programa. Es una práctica terrible. – CheesePls

+2

También hay Try-catch-rethrow o try-catch-wrap-throw, es decir, solo porque pueda manejar la excepción de una manera significativa no significa que haya terminado. El método debe hacer lo que su nombre indica que hará, o debe arrojar una excepción: http://abstractions-r-us.blogspot.com/2010/06/do-your-work-or-throw-exception-example. html. (enchufe desvergonzado para mi blog) – apollodude217

+1

Esta es una pregunta que me he estado preguntando por algún tiempo. Creo que intento usar bloques try-catch si es necesario con excepciones definidas por el usuario. Excepción. Pero tendré que decir que una tirada en el stub del método es mucho más limpia y menos código para tener que ordenar más adelante si tiene que hacer alguna depuración. Si usas un throw en el stub del método, debes atrapar el error en la cadena de métodos, creo, esto no estoy seguro. Con un try-catch puede hacer que el try-catch capte el error sin tener que pasarlo por la cadena de métodos. No estoy completamente seguro de esto, pero creo que –

3

La decisión de añadir un try-catch o una cláusula throws a sus métodos depende de "cómo quiere (o tiene) para manejar su excepción".

Cómo manejar una excepción es una amplia y lejos de pregunta trivial para responder. Involucra especialmente la decisión de dónde manejar la excepción y qué acciones implementar dentro del bloque catch. De hecho, cómo manejar una excepción debe ser una decisión de diseño global.

Respondiendo a sus preguntas, no hay una regla práctica.

usted tiene que decidir dónde quiere manejar su excepción y que la decisión es generalmente muy específicos a sus requisitos de dominio y de aplicación.

1

Un método debería ser solo throws una excepción si puede ofrecer garantías razonables sobre el estado del objeto, los parámetros pasados ​​al método y cualquier otro objeto sobre el que actúe el método. Por ejemplo, un método que se supone que recupera de una colección un elemento que la persona que llama espera contener en él podría ser throws una excepción marcada si el elemento que se esperaba que existiera en la colección, no lo hace. Una persona que llama que detecta esa excepción debe esperar que la colección no contenga el artículo en cuestión.

Nota que mientras Java permitirá excepciones a burbuja comprobado a través de un método que se declara como lanzar excepciones de los tipos apropiados, tal uso debe generalmente ser considerado como un anti-patrón. Imagine, por ejemplo, que algún método LookAtSky() se declara como llamando al FullMoonException, y se espera que lo arroje cuando la Luna está llena; imaginemos además, que LookAtSky() llama a ExamineJupiter(), que también se declara como throws FullMoonException. Si FullMoonException fuera lanzado por ExamineJupiter(), y si LookAtSky() no lo detecta y no lo maneja o lo envuelve en algún otro tipo de excepción, el código que llama a LookAtSky supondría que la excepción fue el resultado de que la luna de la Tierra está llena; no tendría ni idea de que una de las lunas de Júpiter podría ser la culpable.

Las excepciones que una persona que llama puede esperar manejar (incluyendo esencialmente todas las excepciones marcadas) solo deben permitirse filtrar a través de un método si la excepción significará lo mismo para la persona que llama como para el método llamado. Si el código llama a un método que se declara como arrojando alguna excepción marcada, pero la persona que llama no espera que arroje esa excepción en la práctica (por ejemplo, porque cree que es un argumento de método previamente validado), la excepción marcada debe ser capturada y ajustada en algún tipo de excepción sin marcar. Si la persona que llama no espera lanzar la excepción, la persona que llama no puede esperar que tenga un significado particular.

0

Si usa una captura de prueba, cuando se produce la excepción, los códigos restantes se seguirán ejecutando.

Si indica el método para lanzar la excepción, cuando ocurra la excepción, el código dejará de ejecutarse de inmediato.

Cuestiones relacionadas