Menu
Coddy logo textTech

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 está construido sobre una jerarquía de clases bien organizada con raíz en la clase Throwable. Comprender esta jerarquía le ayuda a capturar y manejar excepciones de manera más efectiva.

En la parte superior se encuentra Throwable, el padre de todas las excepciones y errores. Tiene dos subclases directas:

Throwable
├── Error          // Problemas graves (no capturar estos)
└── Exception      // Problemas recuperables
    └── RuntimeException  // Excepciones no verificadas

Error 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 más trabajarás. Se divide en dos categorías: excepciones verificadas (subclases directas de Exception) y excepciones no verificadas (subclases de RuntimeException).

// Clases de excepciones comunes
Exception
├── IOException           // Problemas de archivos/red
├── SQLException          // Problemas de base de datos
└── RuntimeException
    ├── NullPointerException
    ├── ArrayIndexOutOfBoundsException
    └── IllegalArgumentException

Debido a que las excepciones son clases, siguen las reglas de herencia. Cuando capturas un tipo de excepción padre, también capturas todos sus hijos:

try {
    // algún código
} catch (Exception e) {
    // Captura TODAS las excepciones (generalmente demasiado amplio)
}
try {
    // algo de código
} catch (RuntimeException e) {
    // Captura solo excepciones de tiempo de ejecución y subclases
}

Esta jerarquía te permite ser tan específico o general como sea necesario al manejar errores, y es la base para crear tus propias excepciones personalizadas.

challenge icon

Desafío

Fácil

¡Vamos a construir un analizador de excepciones que demuestre cómo funciona la jerarquía de excepciones de Java en la práctica! Crearás un sistema que capture excepciones en diferentes niveles de especificidad e informe qué tipo fue capturado.

Organizarás tu código en tres archivos:

  • ExceptionThrower.java: Crea una clase que pueda activar diferentes tipos de excepciones según la entrada. Tu clase debe tener tres métodos estáticos:

    triggerRuntime(String type) - Basado en la cadena de tipo, lanza diferentes excepciones de tiempo de ejecución (runtime exceptions):

    • Si el tipo es "null", lanza una NullPointerException con el mensaje "Null value encountered"
    • Si el tipo es "index", lanza una ArrayIndexOutOfBoundsException con el mensaje "Invalid index"
    • Si el tipo es "argument", lanza una IllegalArgumentException con el mensaje "Bad argument"

    triggerArithmetic() - Lanza una ArithmeticException con el mensaje "Division error"

    triggerGeneric() - Lanza una RuntimeException con el mensaje "Generic runtime error"

  • ExceptionAnalyzer.java: Crea una clase que capture excepciones en diferentes niveles de jerarquía e identifique qué fue capturado. Incluye estos métodos estáticos:

    analyzeSpecific(String type) - Llama a ExceptionThrower.triggerRuntime(type) dentro de un bloque try. Usa bloques catch separados para NullPointerException, ArrayIndexOutOfBoundsException e IllegalArgumentException. Para cada uno, imprime: Caught specific: [exception class simple name] seguido de Message: [exception message]

    analyzeWithParent() - Llama a ExceptionThrower.triggerArithmetic() dentro de un bloque try. Captúrala usando RuntimeException (el tipo padre). Imprime: Caught via parent: RuntimeException seguido de Actual type: [exception class simple name]

    analyzeWithGrandparent() - Llama a ExceptionThrower.triggerGeneric() dentro de un bloque try. Captúrala usando Exception (un nivel aún más alto en la jerarquía). Imprime: Caught via grandparent: Exception seguido de Actual type: [exception class simple name]

  • Main.java: ¡Une tu analizador de excepciones! Recibirás una entrada: una cadena de tipo de excepción (ya sea "null", "index" o "argument").

    Primero, imprime === Specific Catch === y llama a analyzeSpecific con tu entrada.

    Luego imprime una línea en blanco, === Parent Catch ===, y llama a analyzeWithParent.

    Finalmente, imprime una línea en blanco, === Grandparent Catch ===, y llama a analyzeWithGrandparent.

Recibirás una entrada: el tipo de excepción a activar ("null", "index" o "argument").

Usa e.getClass().getSimpleName() para obtener el nombre de la 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 a todos sus hijos, un concepto clave al decidir qué tan específico debe ser tu manejo de excepciones!

Hoja de referencia

El manejo de excepciones de Java se basa en una jerarquía de clases con raíz en Throwable:

Throwable
├── Error          // Problemas graves (no capturar)
└── Exception      // Problemas recuperables
    └── RuntimeException  // Excepciones no verificadas

Error representa problemas graves de la JVM como OutOfMemoryError o StackOverflowError que las aplicaciones no deberían manejar.

Exception se divide en excepciones verificadas (subclases directas) y excepciones no verificadas (subclases de RuntimeException):

Exception
├── IOException           // Problemas de archivos/red
├── SQLException          // Problemas de base de datos
└── RuntimeException
    ├── NullPointerException
    ├── ArrayIndexOutOfBoundsException
    └── IllegalArgumentException

Capturar un tipo de excepción padre también captura a todos sus hijos:

try {
    // algo de código
} catch (Exception e) {
    // Captura TODAS las excepciones
}

try {
    // algo de código
} catch (RuntimeException e) {
    // Captura solo excepciones de tiempo de ejecución y subclases
}

Use e.getClass().getSimpleName() para obtener el nombre de la clase de la excepción y e.getMessage() para recuperar su mensaje.

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: Imprimir "=== Specific Catch ===" y llamar a ExceptionAnalyzer.analyzeSpecific(type)
        
        // TODO: Imprimir una línea en blanco, luego "=== Parent Catch ===", luego llamar a ExceptionAnalyzer.analyzeWithParent()
        
        // TODO: Imprimir una línea en blanco, luego "=== Grandparent Catch ===", luego llamar a ExceptionAnalyzer.analyzeWithGrandparent()
    }
}
quiz iconPonte a prueba

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