todas tipos salida propagacion mas las excepciones entrada comunes arbol java exception-handling throw

tipos - Lanzar excepciones en Java



tipos de excepciones en java netbeans (11)

¿La primera forma de manejar excepciones no hace exactamente esto (el mecanismo try-throw-catch)? Quiero decir, arroja una excepción y la atrapa con el mismo método.

Esa no es una "forma de manejar excepciones", es una completa tontería. El objetivo de las excepciones es permitir que otro método suba la pila de llamadas. Si va a manejar la condición dentro del mismo método, no tiene sentido usar una excepción: ¡para eso es para ()! Si eso hace que el flujo de control de su método sea demasiado complicado, probablemente debería refactorizar parte de la lógica en métodos separados, y entonces podría tener sentido hacer que esos arrojen excepciones que el cuerpo del método restante capte.

Dicho esto, puedo imaginarme un caso especial en el que podría tener sentido arrojar y atrapar una excepción con el mismo método: cuando ya está llamando a un método que puede arrojar una excepción y tiene un bloque catch para manejarlo, entonces en en algunos casos, podría tener sentido lanzar una excepción para indicar un problema similar que el bloque catch existente puede manejar de la misma manera.

Tengo una pregunta acerca de lanzar excepciones en Java, una especie de malentendido de mi parte, como parece, que me gustaría aclarar por mí mismo.

He estado leyendo que las dos formas básicas de manejar el código de excepción son:

1.) lanzando una excepción en un try-block con "throw new ...", y atrapándolo inmediatamente en un catch-block - el llamado mecanismo try-throw-catch.

2.) lanzando una excepción en un método con "throw new ..." y luego declarando en el encabezado del método que este método podría lanzar una excepción con "throws ..." - el llamado pass-the-buck.

Recientemente leí que "no tiene ningún sentido lanzar una excepción y luego atraparla con el mismo método", lo que me hizo pensar si entendía la cosa de la manera incorrecta, o si la persona que lo había escrito tenía algo otra cosa en mente ¿La primera forma de manejar excepciones no hace exactamente esto (el mecanismo try-throw-catch)? Quiero decir, arroja una excepción y la atrapa con el mismo método. He leído que es una mejor práctica arrojar una excepción en un método, y atraparlo en otro método, pero esta es solo una (probablemente mejor) forma. La otra forma también es legal y correcta, ¿no?

¿Podría, por favor, darme un comentario sobre esto? Muchas gracias.


Con la primera forma, ¿te refieres a algo como esto?

try { ok = doSomething(); if (!ok) { throw new Exception("Error"); } ok = doSomethingElse(); }catch (Exception e) { }

Esto le permitirá salir del bloque try-catch sin ejecutar el resto. Este es el único uso válido que se me ocurre lanzar una excepción con tirar y atraparlo usted mismo en un bloque try-catch. Sin embargo, estándar si se deben usar bloques en su lugar. No entiendo por qué alguien debe lanzar una excepción y luego atraparla él mismo.

La segunda forma es más estándar, especialmente si la persona que llama del método que lanza una excepción es un módulo externo. Esta es una forma de señalar que sucedió algo realmente malo. Es responsabilidad de quien llama manejar la excepción.


Creo que malinterpretaste el primer caso. Normalmente agrega un try-catch-block cuando llama a algún método que puede arrojar excepciones. Atrapar excepciones lanzadas localmente de hecho no tiene mucho sentido. En particular, no debe usar excepciones para salir de los bucles, ya que es extremadamente lento en comparación con un enfoque estándar.


El uso de una excepción para el flujo de control se trata específicamente en Effective Java, 2nd Edition, de Joshua Bloch, artículo 57:

Ítem ​​57: Use excepciones solo para condiciones excepcionales

... las excepciones son, como su nombre lo indica, para ser usadas solo por condiciones excepcionales; nunca deben usarse para el flujo de control ordinario . [cursiva mía]

Entonces, aunque ciertamente "funciona" usar excepciones para controlar el flujo, no se recomienda.


En mi opinión, prueba que los bloques que escribes no deben incluir ningún "lanzamiento nuevo" que estén atrapados dentro del mismo método. Cuando lanzas una excepción, estás diciendo "He encontrado una situación que no puedo manejar, alguien más tendrá que lidiar con ella". Su método con el "lanzamiento nuevo" debe crear una excepción no verificada para lanzar o declarar una excepción marcada en su firma de método.

Si está utilizando clases de terceros que pueden arrojar excepciones, su método debe tener un bloque try / catch si puede manejar la situación si surge una excepción. De lo contrario, debes diferir a otra clase que pueda.

No creo mi propia excepción y luego la atrapo con el mismo método.


La persona que escribió "no tiene ningún sentido lanzar una excepción y luego atraparla con el mismo método" tiene derecho a su opinión, pero no es ampliamente compartida. Hay muchos casos en los que arrojar y atrapar una excepción en el mismo método es lo que se necesita. Lo más simple es cuando estás haciendo una secuencia de operaciones y el fallo de cualquiera de ellas hace que el resto sea inválido. Si detecta que una de estas operaciones falla, es perfectamente razonable lanzar una excepción y capturarla al final del método. De hecho, es la forma lógica de hacer las cosas. Podría decirse que podría reescribir el código para no usar la excepción, tal vez con algunos indicadores de estado y una declaración de interrupción o dos, pero ¿por qué lo haría? El uso de una excepción deja en claro lo que está sucediendo y mejora la legibilidad del código.


La razón por la que eso parecería una tontería (arrojar y atrapar en el mismo método) es porque sería un escenario de uso de excepciones para el control de flujo. Si ya tiene suficientes datos como para identificar la condición en la que debe lanzarse la excepción, entonces podría usar esa información para usar una condición en su lugar.

Vea abajo:

1) Lanzar y atrapar excepciones en el mismo método ( incorrecto )

public void method() { try { workA... workA... workA... workA... if( conditionIvalid() && notEnoughWhatever() && isWrongMoment() ) { throw new IllegalStateException("No the rigth time" ); } workB... workB... workB... workB... } catch( IllegalStateException iee ) { System.out.println( "Skiped workB..."); } workC.... workC.... workC.... workC.... }

En este escenario, el lanzamiento de excepción se usa para omitir la sección "workB".

Esto se haría mejor de esta manera:

2) Usar la condición para controlar el flujo ( derecha )

public void method() { workA... workA... workA... workA... if( !(conditionIvalid() && notEnoughWhatever() && isWrongMoment() ) ) { //throw new IllegalStateException("No the rigth time" ); workB... workB... workB... workB... } workC.... workC.... workC.... workC.... }

Y luego puedes refactorizar la condición:

if( !(conditionIvalid() && notEnoughWhatever() && isWrongMoment() ) ) {

para

if( canProceedWithWorkB() ) {

implementado como:

boolean canProceedWithWorkB() { return !(conditionIvalid() && notEnoughWhatever() && isWrongMoment() ); }


Mi experiencia es que usar el primer método hace que tu código sea rápidamente ilegible, ya que la funcionalidad y el manejo de errores se mezclan. PERO tiene sentido en algunos casos donde tienes un try {} catch {} finaly {} - por ejemplo en el manejo de archivos o bases de datos donde SIEMPRE deseas que se cierre la conexión.

try{ //do something }catch(Exception ex){ //log }finally{ //connection.close }

Para todo lo demás, utilizo la segunda opción, simplemente por la razón de centralizar mis rutinas de manejo de errores y mantener la legibilidad del código que implementa el businesslogic mismo.


Si va a lanzar manualmente una excepción, entonces obviamente sabe que ha habido algún error que debe ser manejado. En lugar de arrojar la nueva excepción, luego atraparla, y luego manejar el error de inmediato, ¿por qué no manejar el error? Usted (y el procesador) no necesitan realizar todo el trabajo de generar una excepción y atraparla. La excepción también hace que el código sea más difícil de leer y depurar.

Lanzaría una excepción, en lugar de simplemente manejar el error de inmediato, si:

  • Otro código, como el código que llamó a su método, debería manejar el error. Por ejemplo, si su código no es código de UI, entonces probablemente no debería generar ventanas. Este es su método # 2.

  • Puedes aprovechar el try, catch, finally block. Es posible que pueda escribir un código más limpio de esta manera, pero creo que el 90% del tiempo su código sería más legible usando declaraciones simples.


Voy a responder a tus preguntas una por una, luego agregaré algunos comentarios hasta el final. No soy una autoridad en el manejo de excepciones, pero espero que mis comentarios sean útiles.

"¿La primera forma de manejar excepciones no hace exactamente esto?

Mi respuesta es sí, como usted lo describe, el primer método funciona al lanzar y atrapar una excepción en el mismo método. Sin embargo, no sé si try-throw-catch tiene que funcionar como lo describes.

"He leído que es una mejor práctica arrojar una excepción en un método, y detectarlo en otro método, pero esta es solo una (probablemente mejor) manera. La otra forma también es legal y correcta, ¿no? "

Estoy de acuerdo en que capturar excepciones de un segundo método es mejor, pero la primera es legal. ¿Es correcto? bueno, eso es para que usted decida, es su código, después de todo.

En general, estoy de acuerdo en que no tiene sentido arrojar una excepción y luego capturar esa excepción de la misma manera. Si hacemos esto porque el método es particularmente largo / complejo y manejar el error usando otra lógica complicaría las cosas más, entonces sugeriría mover parte de esta lógica a otro método y llamar a ese método y capturar su excepción.

Si nuestro código es más simple, entonces puede ser fácil manejar el error usando código que no consiste en lanzar una excepción.

Mis comentarios:

El mecanismo try-throw-catch que mencionaste puede no necesitar la excepción para ser lanzado en el mismo método. Tendría que leer el texto que encontraste para estar seguro, pero esperaría que no sea necesario. Si no necesitó la excepción para ser lanzado en el mismo método, entonces su estrategia de manejo de excepciones es una combinación de 1) y 2).

En el combo, un método usaría el mecanismo try-throw-catch para capturar una excepción lanzada por un método llamado. Me parece que 1) y 2) deberían trabajar juntos para formar su estrategia de manejo de excepciones.

Ahora, tal vez alguien vendrá y nos dará algunas razones maravillosas por las que podríamos lanzar una excepción en el mismo método. Espero que haya algunos, pero a mí me parecen las excepciones, no la regla.

Saludos, Ed


Se deben generar excepciones de un método cuando ese método no sea capaz de resolver la excepción por sí mismo.

Por ejemplo, se FileNotFoundException una FileNotFoundException desde el new FileInputStream(new File( filename )) porque FileInputStream no puede manejar un caso en el que falta un archivo; esa excepción necesita ser lanzada para que la aplicación del usuario final pueda manejar el problema.

En algunos casos, las excepciones se pueden manejar dentro de un método. Por ejemplo, un método de modelo de documento que BadLocationException una BadLocationException podría manejarse dentro de un método suficientemente inteligente. Dependiendo del problema, la excepción puede ser manejada o relanzada.

(De todos modos, argumentaría que lanzar una excepción desde dentro de un bloque try-catch para que el bloque catch pueda ejecutarse representa un flujo lógico realmente malo)