Volver a Java Intermedio

Introducción

El manejo de excepciones es esencial para crear aplicaciones robustas que puedan manejar errores de manera elegante. En este capítulo aprenderás cómo capturar, lanzar y gestionar excepciones en Java.

¿Qué es una Excepción?

Una excepción es un evento que interrumpe el flujo normal de un programa. Java proporciona una forma estructurada de manejar estas situaciones usando bloques try-catch.

try { int resultado = 10 / 0; // ArithmeticException } catch (ArithmeticException e) { System.out.println("¡No se puede dividir por cero!"); }

Tipos de Excepciones

Excepciones Verificadas (Checked):

  • Deben ser capturadas o declaradas
  • Ejemplos: IOException, SQLException
  • Verificadas en tiempo de compilación

Excepciones No Verificadas (Runtime):

  • Opcional capturarlas
  • Ejemplos: NullPointerException, ArrayIndexOutOfBoundsException
  • Verificadas en tiempo de ejecución

Errores:

  • Problemas serios que las aplicaciones no deberían capturar
  • Ejemplos: OutOfMemoryError, StackOverflowError

Try-Catch-Finally

try { FileReader archivo = new FileReader("datos.txt"); // Operaciones de lectura } catch (FileNotFoundException e) { System.out.println("Archivo no encontrado: " + e.getMessage()); } catch (IOException e) { System.out.println("Error leyendo archivo: " + e.getMessage()); } finally { // Siempre se ejecuta, incluso si ocurre una excepción System.out.println("Operaciones de limpieza"); }

Lanzando Excepciones

public void validarEdad(int edad) { if (edad < 0) { throw new IllegalArgumentException("La edad no puede ser negativa"); } if (edad < 18) { throw new IllegalStateException("Debe ser mayor de 18 años"); } }

Excepciones Personalizadas

public class JugadorInvalidoException extends Exception { public JugadorInvalidoException(String mensaje) { super(mensaje); } } public class GestorJuego { public void agregarJugador(String nombre) throws JugadorInvalidoException { if (nombre == null || nombre.isEmpty()) { throw new JugadorInvalidoException("El nombre del jugador no puede estar vacío"); } // Lógica para agregar jugador } }

Try-With-Resources

Cierra recursos automáticamente:

try (FileReader reader = new FileReader("datos.txt"); BufferedReader buffered = new BufferedReader(reader)) { String linea = buffered.readLine(); System.out.println(linea); } catch (IOException e) { System.out.println("Error: " + e.getMessage()); } // No necesita finally - los recursos se cierran automáticamente

Buenas Prácticas

  • Captura excepciones específicas antes que generales
  • No captures excepciones que no puedes manejar
  • Usa mensajes de error significativos
  • Registra las excepciones apropiadamente
  • Usa try-with-resources para recursos AutoCloseable
  • No uses excepciones para control de flujo
  • Crea excepciones personalizadas para errores específicos del dominio

Malas Prácticas Comunes

  • Bloques catch vacíos que ocultan errores
  • Capturar Exception o Throwable demasiado ampliamente
  • No registrar detalles de la excepción
  • Lanzar excepciones sin contexto
  • Usar excepciones para flujo de control normal

Ejemplo Práctico

public class GestorJugadores { public Jugador obtenerJugador(String uuid) throws JugadorNoEncontradoException { Jugador jugador = baseDatos.buscar(uuid); if (jugador == null) { throw new JugadorNoEncontradoException("Jugador no encontrado: " + uuid); } return jugador; } public void procesarJugadores() { List<String> uuids = obtenerUUIDsJugadores(); for (String uuid : uuids) { try { Jugador jugador = obtenerJugador(uuid); jugador.actualizarEstadisticas(); } catch (JugadorNoEncontradoException e) { logger.warn("Saltando jugador: " + e.getMessage()); } catch (Exception e) { logger.error("Error inesperado: " + e.getMessage(), e); } } } }

Conclusión

El manejo adecuado de excepciones es crucial para construir aplicaciones confiables. Al comprender cuándo y cómo usar excepciones, puedes crear código que falle de manera elegante y proporcione información clara de errores.

En el próximo capítulo, exploraremos colecciones avanzadas en Java.