1. Introducción
En este tutorial, veremos los lanzamientos y lanzamientos en Java. Explicaremos cuándo debemos usar cada uno de ellos.
A continuación, mostraremos algunos ejemplos de su uso básico.
2. Lanzamientos y lanzamientos
Comencemos con una introducción rápida. Estas palabras clave están relacionadas con el manejo de excepciones. Se plantean excepciones cuando se interrumpe el flujo normal de nuestra aplicación.
Puede haber muchas razones. Un usuario podría enviar datos de entrada incorrectos. Podemos perder una conexión o puede ocurrir otra situación inesperada. El buen manejo de excepciones es clave para que nuestra aplicación siga funcionando después de la aparición de esos momentos desagradables.
Usamos la palabra clave throw para lanzar explícitamente una excepción del código. Puede ser cualquier método o bloque estático. Esta excepción debe ser una subclase de Throwable. Además, puede ser un Throwable en sí mismo. No podemos lanzar múltiples excepciones con un solo lanzamiento .
La palabra clave Throws se puede colocar en la declaración del método. Denota qué excepciones se pueden lanzar de este método. Debemos manejar estas excepciones con try-catch.
¡Estas dos palabras clave no son intercambiables!
3. Agregue Java
Echemos un vistazo a un ejemplo básico en el que se lanza una excepción del método.
En primer lugar, imagine que estamos escribiendo una calculadora simple. Una de las operaciones aritméticas básicas es la división. Debido a eso, se nos pidió implementar esta función:
public double divide(double a, double b) { return a / b; }
Debido a que no podemos dividir por cero, necesitamos agregar algunas modificaciones a nuestro código existente. Parece que es un buen momento para plantear una excepción.
Hagámoslo:
public double divide(double a, double b) { if (b == 0) { throw new ArithmeticException("Divider cannot be equal to zero!"); } return a / b; }
Como puede ver, hemos utilizado ArithmeticException que se adapta perfectamente a nuestras necesidades. Podemos pasar un solo parámetro de constructor de cadena que es un mensaje de excepción.
3.1. Buenas practicas
Siempre deberíamos preferir la excepción más específica. Necesitamos encontrar una clase que se adapte mejor a nuestro evento excepcional. Por ejemplo, lanza NumberFormatException en lugar de IllegalArgumentException. Debemos evitar lanzar una excepción inespecífica .
Por ejemplo, hay una clase Integer en el paquete java.lang . Echemos un vistazo a la declaración del método de fábrica:
public static Integer valueOf(String s) throws NumberFormatException
Es un método de fábrica estático que crea una instancia de Integer a partir de String. En caso de una cadena de entrada incorrecta , el método arrojará NumberFormatException.
Una buena idea es definir nuestra propia excepción más descriptiva. En nuestra clase Calculadora , podría ser, por ejemplo, DivideByZeroException.
Echemos un vistazo a la implementación de muestra:
public class DivideByZeroException extends RuntimeException { public DivideByZeroException(String message) { super(message); } }
3.2. Envolviendo una excepción existente
A veces queremos incluir una excepción existente en la excepción definida por nosotros.
Comencemos por definir nuestra propia excepción:
public class DataAcessException extends RuntimeException { public DataAcessException(String message, Throwable cause) { super(message, cause); } }
El constructor toma dos parámetros: mensaje de excepción y una causa, que puede ser cualquier subclase de Throwable.
Escribamos una implementación falsa para la función findAll () :
public List findAll() throws SQLException { throw new SQLException(); }
Ahora, en SimpleService , llamemos a una función de repositorio, que puede resultar en SQLException:
public void wrappingException() { try { personRepository.findAll(); } catch (SQLException e) { throw new DataAccessException("SQL Exception", e); } }
Estamos volviendo a lanzar SQLException envuelto en nuestra propia excepción llamada DataAccessException. Todo se verifica mediante la siguiente prueba:
@Test void whenSQLExceptionIsThrown_thenShouldBeRethrownWithWrappedException() { assertThrows(DataAccessException.class, () -> simpleService.wrappingException()); }
Hay dos razones para hacer esto. En primer lugar, usamos el ajuste de excepciones, porque el resto del código no necesita conocer todas las posibles excepciones en el sistema.
Además, los componentes de nivel superior no necesitan conocer los componentes de nivel inferior, ni las excepciones que arrojan.
3.3. Captura múltiple con Java
A veces, los métodos que usamos pueden generar muchas excepciones diferentes.
Echemos un vistazo a un bloque try-catch más extenso:
try { tryCatch.execute(); } catch (ConnectionException | SocketException ex) { System.out.println("IOException"); } catch (Exception ex) { System.out.println("General exception"); }
El método de ejecución puede generar tres excepciones: SocketException, ConnectionException, Exception. El primer bloque de captura capturará ConnectionException o SocketException . El segundo bloque de captura capturaría Exception o cualquier otra subclase de Exception. Recuerde que siempre debemos detectar primero una excepción más detallada.
Podemos intercambiar el orden de nuestros bloques de captura. Entonces, nunca capturaríamos SocketException y ConnectionException porque todo irá a la captura con Exception .
4. Lanza Java
Agregamos throws a la declaración del método.
Let's take a look at one of our previous method declaration:
public static void execute() throws SocketException, ConnectionException, Exception
The method may throw multiple exceptions. They are comma-separated at the end of a method declaration. We can put both, checked and unchecked exceptions in the throws. We have described the difference between them below.
4.1. Checked and Unchecked Exceptions
A checked exception means that it's checked at the compile time. Note, that we must handle this exception. Otherwise, a method must specify an exception by using throws keyword.
The most common checked exceptions are IOException, FileNotFoundException, ParseException. FileNotFoundException may be thrown when we create FileInputStream from File.
There's a short example:
File file = new File("not_existing_file.txt"); try { FileInputStream stream = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); }
We can avoid using try-catch block by adding throws to the method declaration:
private static void uncheckedException() throws FileNotFoundException { File file = new File("not_existing_file.txt"); FileInputStream stream = new FileInputStream(file); }
Unfortunately, a higher level function still has to handle this exception. Otherwise, we have to put this exception in method declaration with throws keyword.
As the opposite, unchecked exceptions aren't checked at the compile time.
The most common unchecked exceptions are: ArrayIndexOutOfBoundsException, IllegalArgumentException, NullPointerException.
Unchecked exceptions are thrown during runtime. The following code will throw a NullPointerException. Probably it's one of the most common exceptions in Java.
Calling a method on a null reference will result in this exception:
public void runtimeNullPointerException() { String a = null; a.length(); }
Let's verify this behavior in the test:
@Test void whenCalled_thenNullPointerExceptionIsThrown() { assertThrows(NullPointerException.class, () -> simpleService.runtimeNullPointerException()); }
Recuerde que este código y la prueba no tienen ningún sentido. Es solo con fines de aprendizaje para explicar las excepciones en tiempo de ejecución.
En Java, cada subclase de Error y RuntimeException es una excepción sin marcar. Una excepción marcada es todo lo demás en la clase Throwable .
5. Conclusión
En este artículo, hemos discutido la diferencia entre dos palabras clave de Java: lanzar y lanzar. Pasamos por el uso básico y hablamos un poco sobre buenas prácticas . Luego hablamos de excepciones marcadas y no marcadas.
Como siempre, el código fuente se puede encontrar en nuestro GitHub.
Si desea profundizar en el manejo de excepciones en Java, consulte nuestro artículo sobre excepciones de Java.