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 comprobadas y las no comprobadas. Esto afecta a cómo debes gestionarlas en tu código.
Las excepciones comprobadas son excepciones que el compilador te obliga a gestionar. Extienden directamente Exception (no a través de RuntimeException). Debes capturarlas o declararlas con throws:
// Debe manejar IOException - es checked
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());
}
}Las excepciones no comprobadas extienden RuntimeException. El compilador no requiere que las gestiones. Normalmente indican errores de programación, como referencias nulas o acceso no válido a un array:
// No se necesita declaración throws
public int divide(int a, int b) {
return a / b; // Puede lanzar ArithmeticException (no comprobada)
}
String name = null;
name.length(); // NullPointerException (no comprobada)Al crear excepciones personalizadas, elige la clase principal según cómo quieras que las personas que llaman las gestionen. Usa excepciones comprobadas para las condiciones recuperables que quien llama debería anticipar. Usa excepciones no comprobadas para errores de programación que no deberían ocurrir en un código correcto.
Desafío
Fácil¡Construyamos un sistema de verificación de edad que demuestre la diferencia clave entre las excepciones comprobadas y no comprobadas! 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 comprobada para los errores de validación de edad. Esta excepción debe extender directamenteException, lo que significa que los llamadores estarán obligados a gestionarla. Incluye un constructor que acepte un mensaje y se lo pase a la clase padre.NegativeAgeException.java: Crea una excepción no comprobada para cuando alguien proporcione una edad negativa (un error de programación que no debería ocurrir con una entrada correcta). Esta debe extenderRuntimeException. Incluye un constructor que acepte y pase un mensaje a la clase padre.AgeVerifier.java: Crea una clase que valide edades usando ambos tipos de excepciones. Incluye dos métodos estáticos:verifyAge(int age): este método debe lanzarNegativeAgeException(no comprobada) con el mensaje"Age cannot be negative: [age]"si la edad es menor que 0. Si la edad es menor que 18, lanzaInvalidAgeException(comprobada) con el mensaje"Must be 18 or older: [age]". De lo contrario, imprimeAge [age] verified successfully. Como este método lanza una excepción comprobada, debes declararlo conthrows InvalidAgeException.verifyAgeUncheckedOnly(int age): este método solo usa excepciones no comprobadas. Si la edad es negativa, lanzaNegativeAgeExceptioncon el mismo formato de mensaje. Si la edad es menor que 18, lanza unaIllegalArgumentExceptioncon el mensaje"Too young: [age]". De lo contrario, imprimeAge [age] verified (unchecked method). ¡Observa que este método no necesita ninguna declaraciónthrows!Main.java: ¡Integra tu sistema de verificación! Recibirás una entrada: una edad (entero).Primero, imprime
=== Checked Exception Method ===y llama averifyAgecon la edad de entrada. Como lanza una excepción comprobada, debes incluirlo en un bloque try-catch. CapturaInvalidAgeExceptione imprimeChecked exception caught: [message]. Captura tambiénNegativeAgeExceptione imprimeUnchecked exception caught: [message].Después, imprime una línea en blanco y
=== Unchecked Exception Method ===. Llama averifyAgeUncheckedOnlycon la misma edad. Aunque este método puede lanzar excepciones, no estás obligado a capturarlas. Sin embargo, inclúyelo de todos modos en un bloque try-catch para gestionar los errores correctamente. CapturaNegativeAgeExceptione imprimeRuntime exception caught: [message]. CapturaIllegalArgumentExceptione imprimeIllegal argument caught: [message].
Recibirás una entrada: un entero que representa la edad que se debe verificar.
Observa la diferencia clave: el método con la excepción comprobada requiere una declaración throws y obliga a los llamadores a gestionarla, mientras que el método no comprobado se compila correctamente sin ningún manejo de excepciones. ¡Esta es la distinción fundamental entre las excepciones comprobadas y no comprobadas en Java!
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: Test the checked exception method
// Print: "=== Checked Exception Method ==="
// Llama a AgeVerifier.verifyAge(age) en un try-catch
// - Catch InvalidAgeException: print "Checked exception caught: [message]"
// - Catch NegativeAgeException: print "Unchecked exception caught: [message]"
// TODO: Print a blank line, then "=== Unchecked Exception Method ==="
// Llama a AgeVerifier.verifyAgeUncheckedOnly(age) en un try-catch
// - Catch NegativeAgeException: print "Runtime exception caught: [message]"
// - Catch IllegalArgumentException: print "Illegal argument caught: [message]"
}
}
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