CodeGym /Cursos /JAVA 25 SELF /finally y throw: finalización y generación de excepciones...

finally y throw: finalización y generación de excepciones

JAVA 25 SELF
Nivel 11, Lección 3
Disponible

1. Introducción al bloque finally

Cuando trabajas con recursos — archivos, conexiones de red, bases de datos — es importante asegurarte de que se cierren o se liberen siempre, incluso si durante el proceso ocurre un error. En Java existe un bloque especial para ello — finally.

¿Cómo funciona finally?

El bloque finally es parte de la construcción try-catch-finally. El código dentro de finally se ejecuta siempre (si está escrito), independientemente de si hubo o no una excepción. Incluso si en try hubo un return o se lanzó una excepción — finally se ejecutará de todos modos (salvo que se apague el ordenador o se finalice el programa por la fuerza mediante System.exit(0)).

Sintaxis:

try {
    // Código donde puede ocurrir una excepción
} catch (ExceptionType e) {
    // Manejo del error
} finally {
    // ¡Este código se ejecutará siempre!
}

Ejemplo

try {
    System.out.println("Inicio de la ejecución");
    int result = 10 / 0; // aquí se producirá un error
    System.out.println("Resultado: " + result);
} catch (ArithmeticException e) {
    System.out.println("Error: división por cero");
} finally {
    System.out.println("Este código se ejecutará en cualquier caso");
}

Resultado de la ejecución:

Inicio de la ejecución
Error: división por cero
Este código se ejecutará en cualquier caso

¿Qué ocurre?

  1. En try intentamos dividir dos números y obtenemos un error.
  2. Si al dividir se produjo un error, catch lo manejará.
  3. ¡Pero! En cualquier caso finally se ejecutará y escribirá un mensaje en la consola.

2. finally sin catch

Pueden existir 3 variantes de la construcción:

  • Completa: try-catch-finally
  • Sin finally: try-catch
  • Sin catch: try-finally

La tercera variante se utiliza cuando el método de un nivel superior será quien capture y maneje el error. Pero el bloque finally es necesario para garantizar la ejecución de cierto código:

  • Cierre de archivos, conexiones de red, bases de datos.
  • Liberación de cualquier recurso (por ejemplo, bloqueos).
  • Registro en logs: escribir información sobre la finalización de la operación.

Ejemplo:

try {
    System.out.println("Dividimos números");
    int result = 10 / 0;   // ¡error!
    System.out.println("Resultado: " + result);
} finally {
    System.out.println("El bloque finally se ha ejecutado");
}

Resultado:

Dividimos números
El bloque finally se ha ejecutado
Exception in thread "main" java.lang.ArithmeticException: / by zero

¿Cuándo NO se ejecuta finally?

Casi siempre se ejecuta. Excepciones — si:

  1. Se finaliza el programa por la fuerza con: System.exit(0).
  2. Se “mata” por la fuerza el hilo donde se ejecuta finally.
  3. Se apaga el ordenador.

3. Operador throw: cómo generar una excepción manualmente

A veces Java “lanza” excepciones por sí misma (por ejemplo, división por cero, acceso fuera de los límites de un array). Pero hay situaciones en las que tú quieres indicar explícitamente: «¡Esto es un error! ¡No puedo continuar la ejecución!». Para ello en Java existe el operador throw.

Analogía: Si estás en una tienda y ves un producto caducado — “lanzas” una queja. Así en el código: si algo está mal, lanzas una excepción.

Sintaxis de throw

throw new ExceptionType("Mensaje de error");

ExceptionType — cualquier clase que herede de Throwable (normalmente Exception o RuntimeException). Entre paréntesis — el mensaje que ayudará a entender qué salió mal.

Ejemplo: validación de argumentos del método

public static int safeDivide(int a, int b) {
    if (b == 0) {
        throw new IllegalArgumentException("El divisor no puede ser cero");
    }
    return a / b;
}

Uso:

public static void main(String[] args) {
    try {
        int result = safeDivide(10, 0);
        System.out.println("Resultado: " + result);
    } catch (IllegalArgumentException e) {
        System.out.println("Error: " + e.getMessage());
    }
}

Resultado:

Error: El divisor no puede ser cero

¿Cuándo usar throw?

  • Validación de argumentos del método (por ejemplo, si llega null o datos no válidos).
  • Comprobación del estado del objeto (por ejemplo, intentar retirar dinero de una cuenta con 0 euros).
  • Dentro de catch — si quieres “relanzar” la excepción más arriba (por ejemplo, añadir información adicional).

4. Combinación de try-catch-finally y throw

A veces estas construcciones trabajan juntas. Por ejemplo, capturas un error, pero después decides lanzar uno propio, más informativo.

public static int parseAndDivide(String text, int divisor) {
    try {
        int number = Integer.parseInt(text);
        if (divisor == 0) {
            throw new IllegalArgumentException("El divisor no puede ser cero");
        }
        return number / divisor;
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("La cadena '" + text + "' no es un número");
    } finally {
        System.out.println("Intento de procesar la cadena: " + text);
    }
}

Uso:

try {
    int result = parseAndDivide("42a", 2);
    System.out.println("Resultado: " + result);
} catch (IllegalArgumentException e) {
    System.out.println("Error: " + e.getMessage());
}

Resultado:

Intento de procesar la cadena: 42a
Error: La cadena '42a' no es un número

Matiz importante: return y finally

¡Incluso si en el bloque try hay un return, finally se ejecutará igualmente!

public static int getValue() {
    try {
        return 10;
    } finally {
        System.out.println("¡finally se ejecutará igualmente!");
    }
}

La llamada a getValue() mostrará:

¡finally se ejecutará igualmente!

5. Errores típicos al usar finally y throw

Error n.º 1: olvidaste cerrar un recurso sin finally.
Un problema muy común: abriste un archivo y no lo cerraste — se produjo una fuga de recursos. Usa siempre finally (o try-with-resources, del que hablaremos más adelante).

Error n.º 2: lanzaste una excepción, pero no la manejaste.
Si lanzas una excepción con throw, pero en ninguna parte la capturas (no hay try-catch), el programa terminará de forma anómala. Piensa siempre quién va a capturar tu excepción.

Error n.º 3: return en finally.
Si por error escribes return dentro de finally, “anulará” cualquier return o throw anteriores. Esto puede conducir a bugs muy difíciles de detectar. ¡No se recomienda en absoluto hacerlo!

public int tricky() {
    try {
        return 1;
    } finally {
        return 2; // PELIGRO: ¡devolverá 2, no 1!
    }
}

Resultado: se devolverá 2, aunque en try había 1.

Error n.º 4: pérdida de información de la excepción.
Si capturas una excepción y luego lanzas otra nueva sin conservar la información de la anterior (e), pierdes la traza de llamadas, lo que dificulta la depuración. Es mejor escribir así:

catch (NumberFormatException e) {
    throw new IllegalArgumentException("Error de conversión", e);
}
1
Tarea
JAVA 25 SELF, nivel 11, lección 3
Bloqueada
Robot aspirador y su informe de finalización 🧹
Robot aspirador y su informe de finalización 🧹
1
Tarea
JAVA 25 SELF, nivel 11, lección 3
Bloqueada
Sistema de puntuación: ¡solo valores positivos! 🏅
Sistema de puntuación: ¡solo valores positivos! 🏅
1
Tarea
JAVA 25 SELF, nivel 11, lección 3
Bloqueada
Módulo crítico y terminación de emergencia con informe 💥
Módulo crítico y terminación de emergencia con informe 💥
1
Tarea
JAVA 25 SELF, nivel 11, lección 3
Bloqueada
Validación del nombre de usuario en el sistema de registro 📝
Validación del nombre de usuario en el sistema de registro 📝
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION