Menu
Coddy logo textTech

Errores Checked vs Unchecked

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 61 de 87.

Has visto que la jerarquía de excepciones de Java se divide en diferentes ramas. La distinción clave que debes entender es entre las excepciones checked (verificadas) y unchecked (no verificadas); esto afecta a cómo debes manejarlas en tu código.

Las excepciones verificadas son excepciones que el compilador te obliga a manejar. Extienden Exception directamente (no a través de RuntimeException). Debes capturarlas o declararlas con throws:

// Debe manejar IOException - es una excepción comprobada
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);  // Puede lanzar IOException
}

// O capturarla
public void readFileSafe(String path) {
    try {
        FileReader reader = new FileReader(path);
    } catch (IOException e) {
        System.out.println("File error: " + e.getMessage());
    }
}

Excepciones no verificadas extienden RuntimeException. El compilador no requiere que las manejes; normalmente indican errores de programación como referencias nulas o accesos a arreglos inválidos:

// No se necesita la declaración throws
public int divide(int a, int b) {
    return a / b;  // Puede lanzar ArithmeticException (unchecked)
}

String name = null;
name.length();  // NullPointerException (unchecked)

Al crear excepciones personalizadas, elija la clase padre en función de cómo desea que quienes las llaman las manejen. Utilice excepciones verificadas para condiciones recuperables que el llamador debería anticipar. Utilice excepciones no verificadas para errores de programación que no deberían ocurrir en un código correcto.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de verificación de edad que demuestre la diferencia clave entre las excepciones verificadas (checked) y no verificadas (unchecked)! Crearás excepciones personalizadas de ambos tipos y verás cómo el compilador las trata de manera diferente.

Organizarás tu código en cuatro archivos:

  • InvalidAgeException.java: Crea una excepción verificada para fallos de validación de edad. Esta excepción debe extender directamente de Exception, lo que significa que los llamadores estarán obligados a manejarla. Incluye un constructor que acepte un mensaje y lo pase a la clase padre.
  • NegativeAgeException.java: Crea una excepción no verificada para cuando alguien proporcione una edad negativa (un error de programación que no debería ocurrir con una entrada correcta). Esta debe extender de RuntimeException. Incluye un constructor que acepte y pase un mensaje al padre.
  • AgeVerifier.java: Crea una clase que valide edades utilizando ambos tipos de excepciones. Incluye dos métodos estáticos:

    verifyAge(int age) - Este método debe lanzar NegativeAgeException (no verificada) con el mensaje "Age cannot be negative: " + age si la edad es menor que 0. Si la edad es menor que 18, lanza InvalidAgeException (verificada) con el mensaje "Must be 18 or older: " + age. De lo contrario, imprime "Age " + age + " verified successfully". Dado que este método lanza una excepción verificada, debes declararlo con throws InvalidAgeException.

    verifyAgeUncheckedOnly(int age) - Este método solo utiliza excepciones no verificadas. Si la edad es negativa, lanza NegativeAgeException con el mismo formato de mensaje. Si la edad es menor que 18, lanza una IllegalArgumentException con el mensaje "Too young: " + age. De lo contrario, imprime "Age " + age + " verified (unchecked method)". ¡Nota que este método no necesita una declaración throws!

  • Main.java: ¡Une tu sistema de verificación! Recibirás una entrada: una edad (entero).

    Primero, imprime "=== Checked Exception Method ===" y llama a verifyAge con la edad de entrada. Dado que lanza una excepción verificada, debes envolverla en un try-catch. Captura InvalidAgeException e imprime "Checked exception caught: " + e.getMessage(). También captura NegativeAgeException e imprime "Unchecked exception caught: " + e.getMessage().

    Luego imprime una línea en blanco y "=== Unchecked Exception Method ===". Llama a verifyAgeUncheckedOnly con la misma edad. Aunque este método puede lanzar excepciones, no estás obligado a capturarlas. Sin embargo, envuélvelo en un try-catch de todos modos para manejar los errores con elegancia. Captura NegativeAgeException e imprime "Runtime exception caught: " + e.getMessage(). Captura IllegalArgumentException e imprime "Illegal argument caught: " + e.getMessage().

Recibirás una entrada: un número entero que representa la edad a verificar.

Observa la diferencia clave: el método con la excepción verificada requiere una declaración throws y obliga a los llamadores a manejarla, mientras que el método no verificado compila perfectamente sin ningún manejo de excepciones. ¡Esta es la distinción fundamental entre las excepciones verificadas y no verificadas en Java!

Hoja de referencia

Las excepciones en Java se dividen en excepciones verificadas (checked) y no verificadas (unchecked), lo que determina cómo el compilador obliga a manejarlas.

Las excepciones verificadas extienden de Exception directamente (no a través de RuntimeException). El compilador te obliga a capturarlas o a declararlas con throws:

// Debe declararse con throws
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);
}

// O capturarla
public void readFileSafe(String path) {
    try {
        FileReader reader = new FileReader(path);
    } catch (IOException e) {
        System.out.println("File error: " + e.getMessage());
    }
}

Las excepciones no verificadas extienden de RuntimeException. El compilador no requiere que las manejes. Normalmente indican errores de programación:

// No se necesita declaración throws
public int divide(int a, int b) {
    return a / b;  // Puede lanzar ArithmeticException (no verificada)
}

String name = null;
name.length();  // NullPointerException (no verificada)

Al crear excepciones personalizadas, elige la clase padre basándote en cómo deben manejarlas quienes llaman al método:

  • Usa excepciones verificadas (extiende Exception) para condiciones recuperables que el llamador debería anticipar
  • Usa excepciones no verificadas (extiende RuntimeException) para errores de programación que no deberían ocurrir en un código correcto

Pruébalo tú mismo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int age = scanner.nextInt();
        
        // TODO: Probar el método de excepción verificada
        // Imprimir: "=== Checked Exception Method ==="
        // Llamar a AgeVerifier.verifyAge(age) en un try-catch
        // - Capturar InvalidAgeException: imprimir "Checked exception caught: [message]"
        // - Capturar NegativeAgeException: imprimir "Unchecked exception caught: [message]"
        
        
        // TODO: Imprimir una línea en blanco, luego "=== Unchecked Exception Method ==="
        // Llamar a AgeVerifier.verifyAgeUncheckedOnly(age) en un try-catch
        // - Capturar NegativeAgeException: imprimir "Runtime exception caught: [message]"
        // - Capturar IllegalArgumentException: imprimir "Illegal argument caught: [message]"
        
    }
}
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