Profe Macón
Programación Avanzada
2.º BT · Tecnologías de la Información
PM
Tienda de Cómics · Código robusto

Cuando algo sale mal

Hasta ahora programamos pensando principalmente en el camino en el que todo funciona. Pero el usuario puede escribir un dato inválido y una regla del negocio puede impedir una operación. Vamos a aprender a detectar, comunicar y manejar excepciones sin convertir try-catch en una receta para copiar.

CET1Excepcionestry / catchthrowNumberFormatExceptionIllegalArgumentException
1 · Partimos de nuestro código

¿Qué pasa si el usuario no escribe un número?

En ProductoController tenemos conversiones como esta:

double precio = Double.parseDouble(vista.getTxtPrecio());

Funciona si el usuario escribe 450 o 450.50. Pero imaginemos que escribe:

JTextField → "cuatrocientos" → Double.parseDouble(...) → ¿?

Java no puede inventar un número que no está ahí. La operación no puede continuar normalmente.

La pregunta de hoy no es “¿cómo evitamos que el usuario se equivoque?”. La pregunta es: ¿qué debe hacer nuestro programa cuando ocurre una situación que impide continuar una operación?
2 · Ponemos nombre al problema

Una excepción interrumpe el flujo normal de una operación

Probemos un ejemplo mínimo, sin Swing:

public class Prueba {
    public static void main(String[] args) {
        String texto = "hola";
        int numero = Integer.parseInt(texto);
        System.out.println(numero);
    }
}

El programa intenta convertir "hola" a int. Como no puede hacerlo, Java genera una excepción.

Definición de trabajo: una excepción es un objeto que representa una situación anormal ocurrida durante la ejecución y que altera el flujo normal de una operación.
Sin manejo

La excepción se propaga y la operación termina abruptamente. En una aplicación gráfica veremos el error en la consola y la acción iniciada por el usuario no se completa.

Con manejo

Podemos detectar esa excepción y decidir qué debe hacer la aplicación: informar, pedir otro dato, cancelar la operación, registrar el problema, etc.

3 · Antes de capturar, aprendemos a leer

El texto rojo también nos da información

Un mensaje típico podría comenzar así:

java.lang.NumberFormatException: For input string: "hola"
  at java.base/java.lang.NumberFormatException.forInputString(...)
  at java.base/java.lang.Integer.parseInt(...)
  at Prueba.main(Prueba.java:4)
TipoNumberFormatException: nos indica qué clase de problema ocurrió.
MensajeFor input string: "hola": aporta datos sobre la causa concreta.
RecorridoLas líneas que comienzan con at muestran por dónde pasó la ejecución hasta llegar al problema. Ese recorrido se llama stack trace.
Hábito útil: no empieces por copiar todo el mensaje en un buscador. Primero identificá el tipo de excepción, el mensaje y la primera línea que pertenece a tu propio código.
4 · Marcamos la operación que puede fallar

try: intentá ejecutar este bloque

Si sabemos que una operación puede generar una excepción que queremos manejar, podemos colocarla dentro de un bloque try:

try {
    int numero = Integer.parseInt(texto);
}

try no evita el problema ni hace desaparecer la excepción. Solo delimita un bloque cuyo resultado vamos a controlar.

Y todavía está incompleto. Si algo falla dentro del try, necesitamos decir qué queremos hacer con esa excepción.
5 · Decidimos qué hacer

catch: si ocurre esta excepción, ejecutá este bloque

try {
    int numero = Integer.parseInt(texto);
    System.out.println(numero);

} catch (NumberFormatException e) {
    System.out.println("El dato ingresado no es un número válido.");
}
try → parseInt() → funciona: continúa
try → NumberFormatException → catch
Muy importante: catch no transforma "hola" en un número. Nos permite decidir cómo responder cuando la conversión no puede realizarse.

¿Qué código deja de ejecutarse?

try {
    int numero = Integer.parseInt(texto); // aquí ocurre la excepción
    System.out.println("Conversión correcta"); // esta línea se salta
}
catch (NumberFormatException e) {
    System.out.println("Dato inválido");
}

System.out.println("El programa continúa");

Cuando se produce la excepción, Java abandona el resto del bloque try, busca un catch compatible y continúa desde allí.

6 · Una sintaxis nueva merece explicación

¿Qué significa catch (NumberFormatException e)?

NumberFormatException

Es el tipo de excepción que este catch sabe manejar.

+
e

Es una variable que referencia al objeto excepción que ocurrió. Podría llamarse de otra manera; e es una convención frecuente.

Ese objeto contiene información. Por ejemplo:

catch (NumberFormatException e) {
    System.out.println(e.getMessage());
}

getMessage() devuelve el mensaje asociado a la excepción.

No hacemos magia: igual que con cualquier objeto, tenemos una referencia (e) y podemos invocar métodos sobre ella.
7 · Volvemos a Tienda de Cómics

El Controller puede manejar errores de formato

Ahora el código que antes podía romper la acción queda protegido:

private void agregarProducto() {
    try {
        long codigo = Long.parseLong(vista.getTxtCodigo());
        String nombre = vista.getTxtNombre();
        double precio = Double.parseDouble(vista.getTxtPrecio());
        int stock = Integer.parseInt(vista.getTxtStock());

        // después continuaremos con la operación...

    } catch (NumberFormatException e) {
        JOptionPane.showMessageDialog(
            vista,
            "Código, precio y stock deben ser números válidos"
        );
    }
}

Acá la ubicación tiene sentido: el Controller está interpretando datos que llegan desde la interfaz.

EntradaResultado
"450"La conversión puede continuar.
"450.50"Puede convertirse a double.
"cuatrocientos"Se produce NumberFormatException y el catch informa al usuario.
campo vacío ""También produce NumberFormatException al intentar convertirlo.
Esto solo resuelve formato. Si el usuario escribe -450, Java lo convierte perfectamente a double. Ahí tenemos otro tipo de problema.
8 · A veces Java no ve ningún problema

throw: nosotros decidimos que la operación no puede continuar

Supongamos que nuestra regla es: el precio debe ser mayor que cero.

double precio = -450;

Para Java ese valor es un double perfectamente válido. Pero para nuestra aplicación no debería aceptarse.

if (precio <= 0) {
    throw new IllegalArgumentException(
        "El precio debe ser mayor que cero"
    );
}

Leamos la línea por partes:

new

Creamos un objeto excepción.

IllegalArgumentException

Representa que el método recibió un argumento que no acepta.

throw

Lanzamos la excepción: la ejecución normal del método se interrumpe y el problema se comunica a quien llamó.

Diferencia central: algunas excepciones aparecen porque Java detecta una operación imposible; otras las lanzamos nosotros cuando una regla de nuestra aplicación impide continuar.
9 · Son dos momentos diferentes

El Service puede lanzar; el Controller puede capturar

En ProductoService:

if (precio <= 0) {
    throw new IllegalArgumentException(
        "El precio debe ser mayor que cero"
    );
}

El Service comunica: “no puedo realizar esta operación”.

En ProductoController:

try {
    service.agregarProducto(codigo, nombre, precio, stock);

} catch (IllegalArgumentException e) {
    JOptionPane.showMessageDialog(vista, e.getMessage());
}

El Controller decide: “¿cómo se lo explico al usuario?”.

Service detecta la regla → throw → excepción viaja → catch → Controller decide la respuesta
La excepción no es un mensaje de pantalla. Es una forma de comunicar que una operación no pudo completarse. El mensaje visual pertenece a quien conoce la interfaz.
10 · Una pregunta legítima

¿Por qué no usar simplemente un if y return?

Solo cortar
if (precio <= 0) {
    return;
}

La operación termina, pero quien llamó puede no saber qué ocurrió ni por qué.

Comunicar el problema
if (precio <= 0) {
    throw new IllegalArgumentException(
        "Precio inválido"
    );
}

La operación termina y el motivo puede ser capturado y tratado en otro nivel.

Esto no significa que todo if deba convertirse en excepción. Los if sirven para tomar decisiones normales del programa. Una excepción tiene sentido cuando estamos diciendo: esta operación no puede continuar como fue solicitada.

Regla práctica: no uses excepciones para reemplazar decisiones normales; usalas para representar situaciones excepcionales o condiciones que impiden completar una operación.
11 · Un mapa mínimo sin adelantarnos demasiado

Java tiene muchas excepciones; hoy necesitamos unas pocas ideas firmes

Exception→RuntimeException→NumberFormatException / IllegalArgumentException

Las excepciones con las que estamos trabajando pertenecen a la familia de excepciones de ejecución. Más adelante veremos otras situaciones en las que Java obliga a declarar o manejar determinadas excepciones.

finally

Existe un bloque que puede ejecutarse ocurra o no una excepción. Lo retomaremos cuando trabajemos con recursos externos.

throws

Permite declarar que un método puede propagar determinadas excepciones. No necesitamos desarrollarlo todavía.

Excepciones propias

También podemos crear clases de excepción específicas del dominio. Lo dejaremos para cuando exista una necesidad real.

Precisión de vocabulario: en clase solemos decir “manejo de errores” en sentido general. Java también posee una clase técnica llamada Error, destinada a fallos graves del entorno que normalmente una aplicación no intenta recuperar. En este material estamos trabajando con excepciones.
12 · Práctica graduada

Probamos, provocamos y manejamos

Mínimo viable

Escribí un programa que intente convertir un texto a int y maneje NumberFormatException.

Checkpoint: ante "hola", el programa muestra un mensaje propio y luego continúa.

Estándar

Adaptá agregarProducto() para manejar errores de conversión de código, precio y stock. Después agregá una regla que lance IllegalArgumentException.

Checkpoint: podés explicar quién lanza y quién captura.

Desafío

Agregá reglas para código, nombre, precio y stock. Diseñá mensajes útiles y evitá catch (Exception e) cuando conocés el tipo concreto que querés manejar.

Checkpoint: cada excepción tiene un motivo identificable.

Casos para probar

CódigoNombrePrecioStock¿Qué debería ocurrir?
101Batman4503Operación válida.
abcBatman4503Error de formato al convertir código.
101Batmancaro3Error de formato al convertir precio.
101Batman-4503La conversión funciona; la regla de negocio debe rechazar el precio.
1014503Regla de negocio: nombre vacío.
Plan de rescate: si throw y arquitectura se mezclan demasiado, volvemos primero a programas mínimos de consola con una sola conversión. Cuando try-catch esté firme, regresamos a Tienda de Cómics.
13 · Comprobamos la comprensión

No alcanza con reconocer la sintaxis

1. ¿Qué bloque decide qué hacer si ocurre una NumberFormatException?

2. Si Double.parseDouble("hola") está dentro de un try, ¿el try logra convertirlo correctamente?

3. El precio -500 es un double válido pero viola nuestra regla. ¿Quién debería detectar esa regla en la arquitectura que estamos construyendo?

4. ¿Qué palabra usamos cuando nuestro código crea y lanza explícitamente una excepción?

5. "tres" escrito en el campo stock provoca un problema de…

14 · Cierre

Una aplicación robusta no supone que todo saldrá bien

try

Delimita código cuya ejecución puede producir una excepción que queremos manejar.

catch

Captura un tipo de excepción y nos permite decidir qué hacer ante ella.

throw

Permite que nuestro propio código comunique que una operación no puede continuar.

entrada → Controller convierte → Service valida reglas → operación o excepción

Micro-entrega de documentación

Completá para Tienda de Cómics una tabla como esta:

SituaciónQuién la detectaTipo de problemaRespuesta esperada
Precio = "abc"ControllerFormato / conversiónInformar que se espera un número.
Precio = -450ServiceRegla de negocioRechazar la operación y comunicar el motivo.
Stock = "tres"ControllerFormato / conversiónInformar que se espera un número.
Código repetidoServiceRegla de negocioRechazar la operación.
Ticket de salida: explicá con tus palabras la diferencia entre throw y catch. No describas solo la sintaxis: decí qué responsabilidad cumple cada uno.

Puente: ahora ya podemos volver a ProductoService sin que throw e IllegalArgumentException aparezcan de la nada. Sabemos qué significan y cómo viaja el problema hasta quien debe manejarlo.

Material en curso
← Índice del curso