Jerarquía de clases de excepciones
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy. Lección 59 de 87.
El sistema de manejo de excepciones de Java se basa en una jerarquía de clases bien organizada cuyo origen es la clase Throwable. Comprender esta jerarquía te ayuda a capturar y manejar las excepciones de forma más eficaz.
En la parte superior se encuentra Throwable, la clase principal de todas las excepciones y errores. Tiene dos subclases directas:
Throwable
├── Error // Problemas serios (no captures estos)
└── Exception // Problemas recuperables
└── RuntimeException // Excepciones no comprobadasError representa problemas graves que las aplicaciones no deberían intentar manejar, como OutOfMemoryError o StackOverflowError. Estos indican problemas fundamentales con la propia JVM.
Exception es la rama con la que trabajarás más. Se divide en dos categorías: excepciones comprobadas (subclases directas de Exception) y excepciones no comprobadas (subclases de RuntimeException).
// Clases de excepciones comunes
Exception
├── IOException // Problemas de archivo/red
├── SQLException // Problemas de base de datos
└── RuntimeException
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── IllegalArgumentExceptionComo las excepciones son clases, siguen las reglas de herencia. Cuando capturas un tipo de excepción padre, también capturas todos sus tipos hijos:
try {
// algo de código
} catch (Exception e) {
// Captura TODAS las excepciones (demasiado amplio generalmente)
}try {
// algún código
} catch (RuntimeException e) {
// Catches only runtime exceptions and subclasses
}Esta jerarquía te permite ser tan específico o general como sea necesario al gestionar errores, y es la base para crear tus propias excepciones personalizadas.
Desafío
Fácil¡Construyamos un analizador de excepciones que demuestre cómo funciona en la práctica la jerarquía de excepciones de Java! Crearás un sistema que capture excepciones en distintos niveles de especificidad e informe qué tipo se capturó.
Organizarás tu código en tres archivos:
ExceptionThrower.java: Crea una clase que pueda activar distintos tipos de excepciones según la entrada. Tu clase debe tener tres métodos estáticos:triggerRuntime(String type): según la cadena de tipo, lanza distintas excepciones en tiempo de ejecución:- Si type es
"null", lanza unaNullPointerExceptioncon el mensaje"Null value encountered" - Si type es
"index", lanza unaArrayIndexOutOfBoundsExceptioncon el mensaje"Invalid index" - Si type es
"argument", lanza unaIllegalArgumentExceptioncon el mensaje"Bad argument"
triggerArithmetic(): lanza unaArithmeticExceptioncon el mensaje"Division error"triggerGeneric(): lanza unaIllegalStateExceptioncon el mensaje"Generic runtime error"(su jerarquía es Exception > RuntimeException > IllegalStateException)- Si type es
ExceptionAnalyzer.java: Crea una clase que capture excepciones en distintos niveles de la jerarquía e identifique qué se capturó. Incluye estos métodos estáticos:analyzeSpecific(String type): llama aExceptionThrower.triggerRuntime(type)dentro de un bloque try. Usa bloques catch separados paraNullPointerException,ArrayIndexOutOfBoundsExceptioneIllegalArgumentException. Para cada uno, imprime:Caught specific: [exception class simple name]seguido deMessage: [exception message]analyzeWithParent(): llama aExceptionThrower.triggerArithmetic()dentro de un bloque try. Captúrala usandoRuntimeException(el tipo padre). Imprime:Caught via parent: RuntimeExceptionseguido deActual type: [exception class simple name]analyzeWithGrandparent(): llama aExceptionThrower.triggerGeneric()dentro de un bloque try. Captúrala usandoException(un nivel aún más alto en la jerarquía). Imprime:Caught via grandparent: Exceptionseguido deActual type: [exception class simple name]Main.java: ¡Une tu analizador de excepciones! Recibirás una entrada: una cadena con el tipo de excepción (ya sea"null","index"o"argument").Primero, imprime
=== Specific Catch ===y llama aanalyzeSpecificcon tu entrada.Después, imprime una línea en blanco,
=== Parent Catch ===y llama aanalyzeWithParent.Por último, imprime una línea en blanco,
=== Grandparent Catch ===y llama aanalyzeWithGrandparent.
Recibirás una entrada: el tipo de excepción que se activará ("null", "index" o "argument").
Usa e.getClass().getSimpleName() para obtener el nombre de clase de la excepción y e.getMessage() para recuperar su mensaje. Este desafío muestra cómo capturar un tipo de excepción padre también captura todos sus tipos derivados: ¡un concepto clave al decidir cuán específico debe ser el manejo de excepciones!
Pruébalo tú mismo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String type = scanner.nextLine();
// TODO: Print "=== Specific Catch ===" and call ExceptionAnalyzer.analyzeSpecific(type)
// TODO: Imprime una línea en blanco, luego "=== Parent Catch ===", luego llama a ExceptionAnalyzer.analyzeWithParent()
// TODO: Print a blank line, then "=== Grandparent Catch ===", then call ExceptionAnalyzer.analyzeWithGrandparent()
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado10Manejo de excepciones en POO
Jerarquía de clases de excepcionesExcepciones personalizadasErrores Checked vs UncheckedPatrón Try With ResourcesResumen - Usuario validado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón IteratorPractica por tu cuenta: Compilador de Java online