1. Clase Throwable: la raíz de todas las excepciones
Ahora veremos en detalle cómo está diseñado el sistema de excepciones en Java: qué es Throwable, en qué se diferencian Exception y Error, y qué significan «comprobada» y «no comprobada». Es el fundamento para un manejo correcto de errores en tus programas.
En Java, todas las excepciones y errores son objetos que heredan de la clase java.lang.Throwable.
Throwable es el «progenitor» de toda la jerarquía de manejo de problemas en Java.
Esquemáticamente:
Throwable
├── Exception
└── Error
Throwable es la clase base de todo lo que puede ser «lanzado» (throw) y «capturado» (catch) en Java. No se utiliza directamente: sirve como base para tipos de error más concretos.
Exception — para errores «normales»
Exception es la clase base de todas las excepciones que pueden surgir en un programa y que se pueden y se deben manejar. Son errores «de trabajo»: problemas con archivos, red, entrada/salida, errores del usuario, etc. La mayoría de tus try-catch trabajará con subclases de Exception.
Ejemplos:
- IOException — error al trabajar con archivos o la red.
- SQLException — error al trabajar con la base de datos.
- FileNotFoundException — archivo no encontrado.
Error — para errores fatales de la JVM
Error es la clase base de los errores que ocurren a nivel de la máquina virtual de Java (JVM). Suelen ser fallos críticos que el programa no puede ni debe manejar. Si ocurre Error, lo más probable es que la aplicación no pueda continuar.
Ejemplos:
- OutOfMemoryError — memoria agotada.
- StackOverflowError — desbordamiento de pila (por ejemplo, debido a recursión infinita).
- NoClassDefFoundError — no se encontró la clase necesaria.
Importante:
Capturar y manejar Error casi siempre es una mala idea. No son errores de tu programa, sino fallos del entorno de ejecución.
2. Excepciones checked vs unchecked: ¿qué significa?
En Java, todas las excepciones se dividen en dos grandes grupos:
Excepciones comprobadas (Checked)
¿Qué son? Excepciones que el compilador obliga a manejar o a declarar explícitamente.
¿Cuándo ocurren? Suelen estar asociadas a recursos externos: archivos, red, bases de datos, entrada del usuario.
¿Cómo manejarlas? Hay que envolver el código en try-catch o añadir throws a la firma del método.
Ejemplos: IOException, SQLException, FileNotFoundException
Ejemplo:
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path); // puede lanzar IOException
// ...
}
Si no se manejan ni se propagan — ¡el programa no se compilará!
Excepciones no comprobadas (Unchecked)
¿Qué son? Excepciones que no requieren manejo obligatorio por parte del compilador.
¿Cuándo ocurren? Suelen ser errores en la lógica del programa: división por cero, salida de los límites de un array, acceso a null.
¿Cómo manejarlas? Se pueden capturar, pero no es obligatorio. Es mejor prevenir estos errores con comprobaciones.
¿Dónde en la jerarquía? Todas heredan de RuntimeException.
Ejemplos: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, ArithmeticException
Ejemplo:
int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException
El compilador no te obliga a capturar esta excepción — pero el programa fallará cuando ocurra el error.
3. Toda la jerarquía en una sola imagen
graph TD
Throwable --> Error
Throwable --> Exception
Exception --> RuntimeException
Exception --> CheckedExceptions["(otras excepciones comprobadas)"]
Error --> OutOfMemoryError
Error --> StackOverflowError
RuntimeException --> NullPointerException
RuntimeException --> IndexOutOfBoundsException
RuntimeException --> IllegalArgumentException
%% Estilos
style Throwable fill:#ffa64d,color:#000
style Exception fill:#ffa64d,color:#000
style CheckedExceptions fill:#ffa64d,color:#000
style Error fill:#ff4d4d,color:#fff
style OutOfMemoryError fill:#ff4d4d,color:#fff
style StackOverflowError fill:#ff4d4d,color:#fff
style RuntimeException fill:#4dff88,color:#000
style NullPointerException fill:#4dff88,color:#000
style IndexOutOfBoundsException fill:#4dff88,color:#000
style IllegalArgumentException fill:#4dff88,color:#000
Tabla: diferencias principales
| Grupo | Clase padre | ¿Requiere manejo? | Ejemplos |
|---|---|---|---|
| Checked Exception | |
Sí | |
| Unchecked | |
No | |
| Error | |
No | |
4. ¿Cómo se ve en el código?
Excepción comprobada: ejemplo con archivos
import java.io.*;
public class FileDemo {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
int data = reader.read();
System.out.println(data);
reader.close();
} catch (IOException e) {
System.out.println("Error al trabajar con el archivo: " + e.getMessage());
}
}
}
¡El compilador te obligará a manejar IOException!
Excepción no comprobada: ejemplo de división por cero
public class ExceptionDemo {
public static void main(String[] args) {
int a = 10;
int b = 0;
int c = a / b; // ArithmeticException (unchecked)
System.out.println("Resultado: " + c);
}
}
El compilador no exige manejo, pero el programa fallará.
5. ¿Para qué sirve la jerarquía de excepciones?
- Flexibilidad de manejo: Puedes capturar tanto errores concretos (FileNotFoundException) como grupos enteros (IOException o Exception).
- Reutilización de código: Puedes manejar de forma centralizada errores de un mismo tipo.
- Limpieza del código: La lógica principal no se llena de comprobaciones para cada detalle.
Ejemplo:
try {
// código peligroso
} catch (FileNotFoundException e) {
System.out.println("¡Archivo no encontrado!");
} catch (IOException e) {
System.out.println("¡Error de E/S!");
} catch (Exception e) {
System.out.println("Algo ha salido mal: " + e.getMessage());
}
6. Errores típicos al trabajar con excepciones
Error n.º 1: ignorar las excepciones. Escribir catch (Exception e) {} — ¡malo! Pierdes información sobre la causa del error.
Error n.º 2: capturar demasiado. catch (Exception e) lo atrapa todo, incluso lo que no esperabas. Es mejor capturar solo las excepciones que sabes manejar.
Error n.º 3: capturar errores (Error). No conviene capturar Error si no estás escribiendo código de bajo nivel. Son problemas de la JVM, no de tu programa.
Error n.º 4: no distinguir entre checked y unchecked. ¡No todas las excepciones son iguales! Las checked requieren manejo (Exception); las unchecked, no (RuntimeException y sus subclases).
Error n.º 5: no añadir información a las excepciones. Si creas tus propias excepciones, añade siempre un mensaje informativo.
GO TO FULL VERSION