En Java, tanto Error como Exception son subclases de Throwable. Solo las instancias de Throwable pueden ser lanzadas (throw) o capturadas (catch), formando la base del mecanismo de manejo de excepciones.
Java distingue entre Exception y Error para clasificar diferentes tipos de situaciones anómalas:
Exception: Representa condiciones inesperadas que pueden ocurrir durante la ejecución normal del programa. Estas excepciones son predecibles y, a menudo, manejables mediante la captura y el tratamiento adecuado.Error: Indica problemas graves y generalmente irrecuperables que ocurren en circunstancias excepcionales, a menudo relacionados con el entorno de ejecución o la máquina virtual (JVM). La mayoría de losErrorprovocan un estado inoperable e irrecuperable para el programa. Por su naturaleza, no se recomienda ni es práctico capturarlos. Ejemplos comunes incluyenOutOfMemoryError.
Las Exception se subdividen en dos categorías:
- Excepciones comprobadas (Checked Exceptions): Estas deben ser explícitamente manejadas en el código fuente mediante bloques
try-catcho declaradas en la firma del método (usandothrows). El compilador de Java verifica su manejo. - Excepciones no comprobadas (Unchecked Exceptions): Conocidas también como excepciones de tiempo de ejecución (Runtime Exceptions), no son obligatorias de capturar en tiempo de compilación. Ejemplos típicos son
NullPointerExceptionyArrayIndexOutOfBoundsException. Suelen ser el resultado de errores lógicos en el código que pueden ser prevenidos con una programación cuidadosa.
Relación jerárquica
Tanto Error como Exception heredan de Throwable. A su vez, RuntimeException es una subclase de Exception.
Error y RuntimeException (junto con sus subclases) se consideran excepciones no comprobadas (Unchecked Exceptions). Todas las demás excepciones son excepciones comprobadas (Checked Exceptions).
Diferencias clave
Error: Generalmente se relaciona con problemas a nivel de la máquina virtual, como fallos del sistema, errores de la JVM, falta de memoria o desbordamiento de la pila de llamadas. Ejemplos sonjava.lang.StackOverflowErroryjava.lang.OutOfMemoryError. El compilador no verifica su manejo. Se recomienda que las aplicaciones terminen ante estos errores, ya que son difíciles de rceuperar o prevenir desde el propio programa.Exception: Representa condiciones que el programa puede y debe intentar manejar. Se deben capturar y procesar para intentar que la aplicación continúe su ejecución de forma controlada.
Principios fundamentales para el manejo de excepciones
- Capturar excepciones específicas: Evita capturar excepciones genéricas como
Exception. En su lugar, captura las excepciones específicas que esperas y sabes cómo manejar. Por ejemplo, al usarThread.sleep(), capturaInterruptedException. Esto hace el código más legible y explícito, comunicando claramente la intención del manejo. Además, previene la captura accidental de excecpiones no deseadas, comoRuntimeException, que podrían ser importantes para la depuración. A menos que se haya considerado cuidadosamente, evita capturarThrowableoError, ya que puede ser difícil manejarlos adecuadamente (por ejemplo, unOutOfMemoryError). - No ocultar (swallow) excepciones: Nunca ignores una excepción sin un manejo adecuado. Ocultar excepciones puede llevar a comportamientos impredecibles y a diagnósticos de problemas extremadamente difíciles. Asumir que un bloque de código no lanzará una excepción o que ignorarla es inofensivo es una práctica peligrosa, especialmente en código de producción. Si una excepción no se lanza o no se registra (por ejemplo, en un
Logger), el programa puede terminar de forma incontrolada, y será muy complicado determinar el origen y la causa del fallo.
Ejemplos de errores comunes
java.lang.OutOfMemoryError
Ocurre cuando la JVM no puede asignar más memoria para un objeto porque no hay suficiente espacio libre en el heap.
Ejecutando el siguiente código con una restricción de heap de 150 MB (-Xmx150m) y solicitando 600 MB de memoria:
// Ejemplo de OutOfMemoryError
try {
// Solicita 600MB de memoria
byte[] memoriaGrande = new byte[1024 * 1024 * 600];
} catch (OutOfMemoryError e) {
System.err.println("Error de memoria detectado: " + e.getMessage());
e.printStackTrace();
}
El resultado será:
java.lang.OutOfMemoryError: Java heap space
java.lang.StackOverflowError
Se produce cuando la pila de llamadas de ejecución se desborda, típicamente debido a una recursión demasiado profunda o una recursión infinita.
Considera el siguiente código con una llamada recursiva infinita:
public class StackOverflowDemo {
public static void main(String[] args) {
metodoRecursivoProfundo();
}
public static void metodoRecursivoProfundo() {
// Llamada recursiva infinita
metodoRecursivoProfundo();
}
}
La ejecución generará:
Exception in thread "main" java.lang.StackOverflowError
Otras excepciones comunes
ArrayIndexOutOfBoundsException: Intento de acceder a un índice de array fuera de sus límites válidos.ArithmeticException: Ocurre durante una operación aritmética inválida, como la división por cero.NullPointerException: Se lanza cuando se intenta usar una referencia a un objeto que esnull.IllegalArgumentException: Se lanza cuando un método recibe un argumento ilegal o inapropiado.