El lenguaje de programación Java utiliza excepciones para gestionar errores y otros eventos excepcionales.
Una excepción es un evento que ocurre durante la ejecución de un programa y que altera el flujo normal de las instrucciones. En Java, las excepciones se lanzan de forma explícita, y a ese acto se le denomina lanzar una excepción. El acto de gestionar una excepción se denomina capturar una excepción.
En Java, todas las excepciones son subclases de la clase Exception, que a su vez es una subclase de Throwable.
Java distingue dos tipos de excepciones:
Las excepciones comprobadas son condiciones excepcionales que una aplicación debería prever y de las que debería poder recuperarse.
Un ejemplo de excepción comprobada es FileNotFoundException, que se produce cuando un método intenta leer un fichero que no existe.
Este tipo de excepción se comprueba en tiempo de compilación: los métodos que lanzan excepciones comprobadas deben especificarlo en su firma, y el código que llama a un método que podría lanzar una excepción comprobada debe gestionarla, o el código no compilará.
Todas las excepciones comprobadas son subclases de Exception que no extienden RuntimeException.
Las excepciones no comprobadas son condiciones excepcionales que una aplicación normalmente no puede prever ni de las que puede recuperarse.
Un ejemplo de excepción no comprobada es NullPointerException, que se produce cuando un método que espera un valor distinto de null recibe null.
Este tipo de excepción no se comprueba en tiempo de compilación: no es necesario que los métodos que lanzan excepciones no comprobadas lo especifiquen en su firma, ni que el código que llama a un método que podría lanzar una excepción no comprobada la gestione.
Todas las excepciones no comprobadas heredan de RuntimeException, que a su vez es una extensión de Exception.
Un método en Java puede lanzar una excepción utilizando la instrucción throw.
Cuando se lanza una excepción comprobada desde un método, es necesario especificarlo en la firma del método utilizando la palabra clave throws, como se muestra en el ejemplo siguiente.
Esto obliga al código que llama a prever que puede lanzarse una excepción y a gestionarla en consecuencia.
public class InsufficientBalanceException extends Exception {
}
public class BankAccount {
public void withdraw(double amount) throws InsufficientBalanceException {
if (balance < amount) {
throw new InsufficientBalanceException();
}
// rest of the method implementation
}
}
Cuando se lanza una excepción no comprobada desde un método, no es necesario especificarlo en la firma del método, aunque está permitido.
public class BankAccount {
public void withdraw(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("Cannot withdraw a negative amount");
}
// rest of the method implementation
}
}
Las excepciones en Java se gestionan con las palabras clave try, catch y finally.
try.try le siguen uno o varios bloques catch que capturan las excepciones lanzadas en el bloque try.catch pueden ir seguidos, de forma opcional, de un bloque finally que siempre se ejecuta después del bloque try, independientemente de si se ha lanzado una excepción o no.El siguiente ejemplo muestra cómo funcionan estas palabras clave:
public class ATM {
public void withdraw(BankAccount bankAccount, double amount) {
try {
System.out.println("Withdrawing " + amount);
bankAccount.withdraw(amount);
System.out.println("Withdrawal succeeded");
} catch (InsufficientBalanceException) {
System.out.println("Withdrawal failed: insufficient balance");
} catch (RuntimeException e) {
System.out.println("Withdrawal failed: " + e.getMessage());
} finally {
System.out.println("Current balance: " + bankAccount.getBalance());
}
}
}
En este ejemplo, cuando no se lanza ninguna excepción, se imprime lo siguiente:
Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0
Sin embargo, si la instrucción bankAccount.withdraw(amount) lanza una InsufficientBalanceException, se imprime lo siguiente:
Withdrawing 10.0
Withdrawal failed: insufficient balance
Current balance: 5.0
O, en caso de que la instrucción bankAccount.withdraw(amount) lance una excepción no comprobada, se imprime lo siguiente:
Withdrawing -10.0
Withdrawal failed: Cannot withdraw a negative amount
Current balance: 5.0
Java también tiene una categoría aparte denominada errores, que son problemas graves ajenos a una aplicación.
Un ejemplo de error es OutOfMemoryError, que se produce cuando una aplicación intenta usar más memoria de la que hay disponible en el sistema.
Al igual que las excepciones no comprobadas, los errores no se comprueban en tiempo de compilación. La diferencia es que representan problemas a nivel de sistema y, por lo general, los lanza la máquina virtual de Java o el entorno en lugar de la aplicación. Por lo general, las aplicaciones no deberían intentar capturarlos ni gestionarlos.
Todos los errores en Java heredan de la clase Error.
Como se ha indicado antes, las excepciones son eventos que alteran el flujo normal de las instrucciones y se utilizan para gestionar eventos excepcionales. Por lo tanto, no se recomienda usar excepciones para el control de flujo en tu aplicación.