try excepciones ejemplo catch java if-statement exception throw

excepciones - try catch finally java



¿Debo lanzar excepciones en un bloque if-else? (8)

Aquí está el código:

public Response getABC(Request request) throws Exception { Response res = new Response(); try { if (request.someProperty == 1) { // business logic } else { throw new Exception("xxxx"); } } catch (Exception e) { res.setMessage(e.getMessage); // I think this is weird } return res; }

Este programa está funcionando bien. Creo que debería ser rediseñado, pero ¿cómo?


¿Por qué usaste la declaración try / catch cuando ya tiraste la excepción verificada ?

La excepción marcada generalmente se usa en algunos lenguajes como C ++ o Java, pero no en un lenguaje nuevo como Kotlin. Yo personalmente me limito a usarlo.

Por ejemplo, tengo una clase como esta:

class ApiService{ Response getSomething() throw Exception(); }

que se siente limpio y legible, pero socava la utilidad del mecanismo de manejo de excepciones. En la práctica, getSomething() no ofrece una excepción comprobada, pero ¿necesita comportarse como lo hace? Esto funciona cuando hay alguien corriente arriba de ApiService que sabe cómo lidiar con los errores impredecibles o no evitables como este. Y si realmente puede saber cómo manejarlo, entonces siga adelante y use algo como el ejemplo a continuación, de lo contrario, la Excepción sin marcar sería suficiente.

public Response getSomething(Request req) throws Exception{ if (req.someProperty == 1) { Response res = new Response(); // logic } else { thows Exception("Some messages go here") } }

Os animo a hacer de esta manera:

public Response getSomething(Request req){ if (req.someProperty == 1) { Response res = new Response(); // logic return res; } else { return ErrorResponse("error message"); // or throw RuntimeException here if you want to } }

Para obtener más información, Kotlin , que mencioné anteriormente, no admite la excepción Comprobada debido a muchas razones.

La siguiente es una interfaz de ejemplo del JDK implementado por la clase StringBuilder :

Appendable append(CharSequence csq) throws IOException;

¿Qué dice esta firma? Dice que cada vez que agrego una cadena a algo (un StringBuilder , algún tipo de registro, una consola, etc.) tengo que capturar esas IOExceptions . ¿Por qué? Debido a que podría estar realizando IO (Writer también implementa Appendable ) ... Por lo que resulta en este tipo de código en todo el lugar:

try { log.append(message) } catch (IOException e) { // Must be safe }

Y esto no es bueno, vea Efectivo Java, 3ra edición, artículo 77 : No ignore las excepciones.

Echa un vistazo a estos enlaces:


Creo que podría estar perdiendo el punto de ese try / catch. El código está utilizando el sistema de excepciones para intercalar cualquier mensaje de excepción a la persona que llama. Esto podría estar en lo profundo de una pila de llamadas anidadas, no solo la "tirada" que está mirando.

En otras palabras, la declaración de "lanzamientos" en su código de ejemplo está aprovechando este mecanismo para entregar un mensaje al cliente, pero es casi seguro que no es el principal usuario intentado del intento / captura. (También es una forma descuidada y un poco barata de transmitir este mensaje; puede generar confusión)

Este valor de retorno no es una buena idea de todos modos porque las excepciones a menudo no tienen mensajes y pueden volver a ajustarse ... aunque es mejor que nada. Los mensajes de excepción no son la mejor herramienta para esto, pero manejar una excepción a un nivel alto como este sigue siendo una buena idea.

Lo que quiero decir es que, si refactoriza este código, asegúrese de buscar excepciones en tiempo de ejecución que puedan lanzarse en cualquier lugar de su base de código (al menos en cualquier lugar durante el procesamiento del mensaje), e incluso entonces probablemente debería mantener el mensaje de captura / devolución como un mensaje. atrapa todo en caso de que aparezca una excepción de tiempo de ejecución que no esperabas. No tiene que devolver el error "Mensaje" como el mensaje de su respuesta. Podría ser un poco "No pudimos procesar su solicitud en este momento" en su lugar, pero asegúrese de volcar el seguimiento de la pila en un registro . Actualmente lo estás tirando.


El mecanismo de excepción tiene tres propósitos:

  1. Inmediatamente desactive el flujo normal del programa y vuelva a subir la pila de llamadas hasta que se encuentre un bloque de captura adecuado.
  2. Proporcione el contexto en la forma del tipo de excepción, el mensaje y, opcionalmente, los campos adicionales que el código de bloque de captura puede usar para determinar el curso de acción.
  3. Un seguimiento de pila para que los programadores vean para hacer análisis forense. (Esto solía ser muy caro de hacer).

Esta es una gran cantidad de funcionalidad para que un mecanismo tenga. Para mantener los programas lo más simples posible, para futuros mantenedores, por lo tanto, solo debemos utilizar este mecanismo si es necesario .

En su código de ejemplo, esperaría que cualquier declaración de throw sea ​​algo muy serio que indique que algo está mal y se espera que el código maneje esta emergencia en algún lugar. Tendría que entender qué salió mal y qué tan grave es antes de seguir leyendo el resto del programa. Aquí es solo un elegante regreso de una cuerda, y me rasco la cabeza y me pregunto "¿Por qué fue necesario esto?" y ese esfuerzo extra podría haberse gastado mejor.

Entonces, este código no es tan bueno como puede ser, pero solo lo cambiaría si tuviera el tiempo para hacer una prueba completa también. Cambiar el flujo del programa puede introducir errores sutiles y necesita tener los cambios frescos en su mente si necesita arreglar algo.


En primer lugar, pise con más cuidado cuando refactorice un método de trabajo, especialmente si está realizando una refactorización manual. Dicho esto, la introducción de una variable para mantener el message puede ser una forma de cambiar el diseño:

public Response getABC(Request requst) throw Excetpions { String message = ""; try{ if(request.someProperty == 1){ //business logic else{ message = "xxxx"; } }catch(Exception e){ message = e.getMessage(); } Response res = new Response(); res.setMessage(message); return res; }

El supuesto es que la business logic hace su propio retorno cuando tiene éxito.


Lo mismo si desea obtener el mensaje de excepción específico devuelto por JVM en caso de error, esa vez puede usar el método try-catch con los métodos getMessage () o printStackTrace () en el bloque catch. Así que aquí puedes modificar tu código como:

public Response getABC(Request request) throws Exception { Response res = new Response(); try { if (request.someProperty == 1) { // business logic } } catch (Exception e) { res.setMessage(e.getMessage); } return res; }


No tiene sentido lanzar una excepción en un bloque try e inmediatamente atraparla, a menos que el bloque catch lance una excepción diferente.

Tu código tendría más sentido de esta manera:

public Response getABC(Request request) { Response res = new Response(); if (request.someProperty == 1) { // business logic } else { res.setMessage("xxxx"); } return res; }

Solo necesita el bloque try-catch si su lógica de negocios (ejecutada cuando la condición es true ) puede generar excepciones.

Si no detecta la excepción (lo que significa que la persona que llama tendrá que manejarlo), puede hacerlo sin la cláusula else :

public Response getABC(Request request) throws Exception { if (request.someProperty != 1) { throw new Exception("xxxx"); } Response res = new Response(); // business logic return res; }


Si está lanzando la excepción del método, ¿por qué molestarse en atraparla? puede devolver una respuesta con el mensaje "xxxx" o lanzar una excepción para que la persona que llama a este método lo maneje.

public Response getABC(Request requst) { Response res = new Response(); if(request.someProperty == 1){ //business logic else{ res.setMessage("xxxx"); } } return res; }

O

public Response getABC(Request requst) throw Excetpions { Response res = new Response(); if(request.someProperty == 1){ //business logic else{ throw new Exception("xxxx"); } return res; } public void someMethod(Request request) { try { Response r = getABC(request); } catch (Exception e) { //LOG exception or return response with error message Response response = new Response(); response.setMessage("xxxx"); retunr response; } }


no parece correcto cuando se lanza una excepción a propósito y luego se captura directamente, se puede rediseñar así
puede cambiar throw new Exception("xxxx"); con res.setMessage("xxxx"); ,
y luego puede mantener la parte de excepción de captura para detectar la excepción que puede ocurrir dentro de la lógica de negocios.

public Response getABC(Request requst) { Response res = new Response(); try{ if(request.someProperty == 1){ //business logic else{ res.setMessage("xxxx"); } }catch(Exception e){ res.setMessage(e.getMessage); } return res; }