10. Depuración en IntelliJ IDEA
UD3 — Control de Flujo y Depuración · RA3 — Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje
| Aspecto | Valor |
|---|---|
| Resultado de aprendizaje | RA: 3 — Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje. |
| Criterios de evaluación a los que contribuye esta sección | CE 3.6 (prueba y depura los programas) CE 3.7 (comenta y documenta el código). |
| Marco normativo | RD 405/2023 · RD 450/2010 · RD 659/2023 |
| Tecnología base | Java 25 LTS (OpenJDK Temurin 25) — IntelliJ IDEA Community Edition |
| Horas estimadas | ~3 h (de las 30 h de la UD3). |
Requisitos previos (lo que ya sabes): todas las estructuras de control de UD3: condiciones booleanas y operadores (sección 1);
if/else if/elsey early return (sección 2);switchexpression (sección 3);whileydo-while(sección 4); arrays unidimensionales (sección 5);forclásico y utilidades deArrays(sección 6);for-each(sección 7); bucles anidados, matricesint[][]y sentencias de saltobreak/continue/return(sección 8);try-catch-finallyy manejo de excepciones predefinidas (sección 9). IntelliJ IDEA Community: ya sabes crear proyectos Maven, compilar conShift+F10, y usar atajos básicos (Alt+Enter,Ctrl+Space,Ctrl+Alt+L). Lectura conIO.readln()y conversión conInteger.parseInt/Double.parseDouble.
10.1 ¿De qué va esta sección? — Dejar de adivinar, empezar a ver
Llegas a esta sección con un hábito que vamos a romper: cuando un programa no funciona, tu instinto es meter IO.println por todas partes para ver qué valor tienen las variables. Eso funciona, pero es lento, tedioso y propenso a errores:
- Escribes
IO.println("i = " + i)en 10 sitios. - Ejecutas, ves la salida, descubres que el problema está en otro sitio.
- Borras los
IO.println, añades 10 nuevos en otro sitio. - Repites. Y repites.
Hay una forma mucho mejor: el depurador (debugger) de IntelliJ IDEA. El depurador te permite detener el programa en cualquier punto, ver el valor de todas las variables en ese momento, ejecutar línea a línea y observar cómo cambian los valores. Es como poner el programa en cámara lenta y mirar dentro de su cerebro.
El depurador es la herramienta más importante del programador profesional. Cuando trabajes en una empresa, nadie te dejará meter IO.println en código de producción para buscar un bug. Te esperan con el depurador. Y esta sección es donde lo aprendes a usar bien.
Cubriremos, en este orden:
- Diferencia entre ejecutar y depurar: por qué el botón de depurar es distinto al de ejecutar.
- Breakpoints: puntos donde el programa se detiene.
- Controles de depuración: Step Over, Step Into, Step Out, Resume.
- Ventanas de depuración: Variables, Watches, Console, Frames.
- Evaluate Expression: evaluar expresiones en tiempo de ejecución.
- Breakpoints condicionales: detenerse solo cuando se cumple una condición.
- Flujo de trabajo para encontrar un bug: el método profesional.
- Errores comunes en la depuración.
- Ejemplos resueltos: depurar programas con bugs.
Analogía del médico y la radiografía
Sin depurador, depurar es como un médico que diagnostica a ciegas: el paciente le dice "me duele aquí" y el médico receta algo a ver si funciona. Con depurador, es como tener una radiografía: el médico ve exactamente qué hay dentro, dónde está el problema, y puede actuar con precisión. El depurador es tu radiografía del programa.
Vamos a empezar por lo más básico: la diferencia entre ejecutar y depurar.
10.2 Ejecutar vs. Depurar: dos botones distintos
10.2.1 Ejecutar (Run)
Hasta ahora has usado el botón Run (el triángulo verde) o el atajo Shift+F10 para ejecutar tus programas. Cuando ejecutas, el programa corre de principio a fin sin parar, y solo ves la salida en la consola. Si hay un bug, ves el síntoma (salida incorrecta o excepción) pero no puedes ver qué estaba pasando dentro en el momento del error.
10.2.2 Depurar (Debug)
El botón Debug (el icono del escarabajo verde, "bug") o el atajo Shift+F9 hace lo mismo que Run, pero con superpoderes: el programa se ejecuta línea a línea, se puede detener en los breakpoints que pongas, y puedes inspeccionar variables en cada momento.
| Característica | Run (Shift+F10) |
Debug (Shift+F9) |
|---|---|---|
| Velocidad | Rápido. | Un poco más lento (la JVM se prepara para depurar). |
| Detención | No se detiene (salvo excepciones o fin). | Se detiene en breakpoints. |
| Ver variables | Solo con IO.println manual. |
En la ventana de Variables, automáticamente. |
| Ejecutar línea a línea | No. | Sí (Step Over, Step Into...). |
| Uso | Para probar que el programa funciona. | Para investigar por qué no funciona. |
10.2.3 Cuándo usar cada uno
- Run: cuando el programa ya funciona y quieres ejecutarlo para ver el resultado final. O cuando estás haciendo pruebas rápidas y no necesitas inspeccionar el interior.
- Debug: cuando el programa no funciona como esperas y necesitas investigar por qué. O cuando quieres entender cómo fluye la ejecución de un código que no escribiste tú.
Regla del profesor:
Si el programa funciona, usa Run. Si no funciona, usa Debug. Si quieres entender cómo funciona un código, usa Debug.
10.3 Breakpoints: detener el programa
10.3.1 Qué es un breakpoint
Un breakpoint (punto de interrupción) es una marca que pones en una línea de código. Cuando depuras el programa y la ejecución llega a esa línea, el programa se detiene y te cede el control. A partir de ahí, puedes:
- Ver el valor de todas las variables en ese momento.
- Ejecutar línea a línea.
- Continuar la ejecución hasta el siguiente breakpoint.
10.3.2 Cómo poner un breakpoint
La forma más simple: haz clic en el margen izquierdo del editor, a la izquierda del número de línea. Aparecerá un punto rojo:
flowchart LR
A["Clic en margen izquierdo"] --> B["Aparece punto rojo ●"]
B --> C["Breakpoint activo"]
C --> D["El programa se detendrá aquí al depurar"]
Para quitarlo: vuelve a hacer clic en el mismo sitio y el punto rojo desaparece.
Atajo de teclado: Ctrl+F8 (Windows/Linux) o Cmd+F8 (Mac) sobre la línea donde quieres poner el breakpoint.
10.3.3 Ejemplo: detener el programa en una línea
Si pones un breakpoint en la línea del for y pulsas Shift+F9 (Debug), el programa se detendrá en la primera iteración del bucle, justo antes de ejecutar suma = suma + numeros[i]. Verás:
- La variable
icon valor0. - La variable
sumacon valor0. - El array
numeroscon sus 5 valores.
10.3.4 Múltiples breakpoints
Puedes poner tantos breakpoints como quieras. El programa se detiene en el primero que encuentre. Cuando lo reanudes (con F9), corre hasta el siguiente breakpoint.
10.3.5 Breakpoint en una línea con varias sentencias
Un breakpoint se pone en una línea de código. Si la línea tiene varias sentencias (poco habitual en Java), el breakpoint se activa al inicio de la línea.
10.3.6 Lo que NO es un breakpoint
- No es un
IO.println: no imprime nada en la consola. - No es un
if: no tiene condición (aunque los breakpoints condicionales sí la tienen; ver 10.7). - No detiene el programa cuando lo ejecutas con Run (
Shift+F10): solo funciona con Debug (Shift+F9).
10.4 Controles de depuración: ejecutar línea a línea
Una vez que el programa está detenido en un breakpoint, tienes varios controles para ejecutarlo línea a línea. Son los más importantes del depurador y los que vas a usar siempre.
10.4.1 Step Over (F8)
Ejecuta la línea actual y avanza a la siguiente. Si la línea actual contiene una llamada a un método, no entra dentro del método: lo ejecuta entero y se detiene en la línea siguiente.
Step Over es el control que vas a usar el 90 % de las veces. Te permite avanzar línea a línea sin perderte dentro de métodos que ya funcionan.
10.4.2 Step Into (F7)
Entra dentro del método que se está llamando en la línea actual. Si la línea tiene una llamada a un método, en vez de ejecutarlo entero, se detiene en la primera línea del método.
Step Into lo usas cuando sospechas que el bug está dentro del método que se llama en esta línea. Si el método ya funciona (p. ej., Integer.parseInt o IO.readln), no uses Step Into: te meterás en código del API de Java que no te interesa.
10.4.3 Step Out (Shift+F8)
Sale del método actual y vuelve a quien lo llamó. Si estás dentro de un método y ya has visto lo que querías, Step Out te lleva de vuelta al llamador, en la línea siguiente a la que te llamó.
10.4.4 Resume (F9)
Continúa la ejecución hasta el siguiente breakpoint (o hasta el fin del programa si no hay más breakpoints). Útil cuando ya has inspeccionado lo que querías y quieres dejar correr el programa hasta la próxima parada.
10.4.5 Stop (Ctrl+F2)
Detiene el programa y la depuración. Cierra la sesión de depuración y vuelve al editor. Útil cuando ya has encontrado el bug y quieres corregir el código.
10.4.6 Tabla resumen de controles
| Control | Atajo (Win/Linux) | Atajo (Mac) | Qué hace |
|---|---|---|---|
| Step Over | F8 |
F8 |
Ejecuta la línea actual, no entra en métodos. |
| Step Into | F7 |
F7 |
Entra dentro del método de la línea actual. |
| Step Out | Shift+F8 |
Shift+F8 |
Sale del método actual y vuelve al llamador. |
| Resume | F9 |
F9 |
Continúa hasta el siguiente breakpoint. |
| Stop | Ctrl+F2 |
Cmd+F2 |
Detiene el programa y la depuración. |
10.4.7 Diagrama de los controles
flowchart TD
Detenido["Programa detenido en breakpoint"] --> Pregunta{"¿Qué quieres hacer?"}
Pregunta -->|"Avanzar una línea\n(sin entrar en métodos)"| Over["Step Over (F8)"]
Pregunta -->|"Entrar en el método\nde la línea actual"| Into["Step Into (F7)"]
Pregunta -->|"Salir del método actual\ny volver al llamador"| Out["Step Out (Shift+F8)"]
Pregunta -->|"Continuar hasta el\nsiguiente breakpoint"| Resume["Resume (F9)"]
Pregunta -->|"Detener todo"| Stop["Stop (Ctrl+F2)"]
Over --> Detenido2["Programa detenido en la siguiente línea"]
Into --> Detenido3["Programa detenido en la primera línea del método"]
Out --> Detenido4["Programa detenido en el llamador"]
Resume --> Detenido5["Programa corre hasta el próximo breakpoint"]
Stop --> Fin([Fin de la depuración])
Detenido2 --> Detenido
Detenido3 --> Detenido
Detenido4 --> Detenido
Detenido5 --> Detenido
10.5 Ventanas de depuración
Cuando el programa está detenido en un breakpoint, IntelliJ te muestra varias ventanas con información. Las más importantes son:
10.5.1 Ventana Variables
Muestra todas las variables accesibles en el punto donde está detenido el programa, con sus valores actuales. Es la ventana que más vas a mirar.
Para los arrays, puedes expandirlos (clic en la flecha > al lado del nombre) y ver cada elemento:
10.5.2 Ventana Watches
Te permite añadir expresiones personalizadas que quieres vigilar. Por ejemplo, puedes añadir numeros[i] o i < numeros.length y ver su valor en cada paso.
Para añadir un watch: clic en el botón + de la ventana Watches (o Alt+Insert sobre ella) y escribe la expresión.
| Ventana | Qué muestra | Cuándo usarla |
|---|---|---|
| Variables | Todas las variables accesibles. | Siempre: para ver el estado del programa. |
| Watches | Expresiones que tú eliges. | Cuando quieres vigilar una expresión concreta (p. ej., numeros[i] dentro de un bucle). |
10.5.3 Ventana Console
La consola normal: muestra la salida del programa (IO.println) y la entrada del usuario (IO.readln). Mientras depuras, puedes interactuar con el programa por la consola igual que cuando lo ejecutas con Run.
10.5.4 Ventana Frames
Muestra la pila de llamadas (call stack): la lista de métodos que están en ejecución, desde el más interno hasta main. Útil para entender cómo llegaste al punto donde estás.
En UD3 todos tus programas tienen main solo, así que la pila es corta. Cuando veas métodos propios en UD4, la pila será más larga y esta ventana será más útil.
10.6 Evaluate Expression: evaluar en tiempo de ejecución
10.6.1 Qué es
Evaluate Expression (Alt+F8) te permite escribir cualquier expresión Java y ver su valor en el punto donde está detenido el programa. Es como un mini-interprete de Java que tiene acceso a todas las variables del programa en ese momento.
10.6.2 Ejemplo
El programa está detenido en la línea suma = suma + numeros[i]; con i = 2 y suma = 30. Pulsas Alt+F8 y escribes:
Evaluate Expression es muy potente para investigar: puedes probar expresiones sin modificar el código, ver qué pasaría si los valores fuesen distintos, etc.
10.6.3 Cuándo usarlo
- Para ver el valor de una expresión compleja que no está como variable.
- Para probar qué pasaría con distintos valores sin modificar el código.
- Para comprobar el resultado de una operación antes de ejecutar la línea.
10.7 Breakpoints condicionales
10.7.1 Qué son
Un breakpoint condicional se detiene solo cuando se cumple una condición. En vez de parar en cada iteración de un bucle (que para 1000 iteraciones sería impresentable), puedes parar solo cuando i == 500 o cuando numeros[i] < 0.
10.7.2 Cómo poner uno
- Pon un breakpoint normal (clic en el margen).
- Haz clic derecho sobre el punto rojo.
- Aparece un diálogo. En el campo Condition, escribe una expresión booleana:
- El punto rojo se convierte en un punto rojo con un signo
=dentro, indicando que es condicional.
Ahora el programa solo se detiene cuando i == 500. Las demás iteraciones pasan de largo.
10.7.3 Ejemplos de condiciones
| Condición | Cuándo se detiene |
|---|---|
i == 50 |
En la iteración 50 del bucle. |
numeros[i] < 0 |
Cuando encuentra un número negativo. |
suma > 100 |
Cuando la suma acumulada supera 100. |
nombre.equals("Ana") |
Cuando el nombre es "Ana". |
i % 100 == 0 |
Cada 100 iteraciones (en bucles grandes). |
10.7.4 Cuándo usarlos
Los breakpoints condicionales son esenciales para depurar bucles con muchas iteraciones. Sin ellos, tendrías que pulsar F8 (Step Over) cientos de veces para llegar a la iteración que te interesa. Con un breakpoint condicional, el programa corre solo y se detiene justo en la iteración que quieres.
10.8 Flujo de trabajo para encontrar un bug
Vamos a ver el método profesional para encontrar un bug. Sigue estos pasos en orden:
10.8.1 Paso 1: Reproducir el bug
Antes de depurar, asegúrate de que puedes reproducir el error. Si el bug no aparece siempre, necesitas saber qué entrada lo provoca. Anota la entrada que produce el error.
10.8.2 Paso 2: Localizar la zona sospechosa
Lee el código y piensa: ¿dónde puede estar el error? No pongas breakpoints por todo el programa: pon breakpoints en la zona sospechosa. Si es un bucle, pon un breakpoint en la primera línea del bucle. Si es un if, pon un breakpoint en la condición.
10.8.3 Paso 3: Depurar (Shift+F9)
Pulsa Shift+F9 (Debug). El programa corre hasta el primer breakpoint y se detiene.
10.8.4 Paso 4: Inspeccionar variables
Mira la ventana Variables. ¿Tienen los valores que esperabas? Si una variable tiene un valor inesperado, ya sabes por dónde empezar a investigar.
10.8.5 Paso 5: Ejecutar línea a línea (F8)
Pulsa F8 (Step Over) repetidamente. Observa cómo cambian las variables en cada línea. Cuando una variable cambia a un valor inesperado, esa línea es la culpable.
10.8.6 Paso 6: Si la línea llama a un método, entrar con F7
Si la línea que cambia el valor de forma inesperada contiene una llamada a un método, pulsa F7 (Step Into) para entrar dentro y ver qué pasa.
10.8.7 Paso 7: Corregir y probar
Cuando hayas encontrado el error, detén la depuración (Ctrl+F2), corrige el código, y vuelve a ejecutar (Shift+F10 o Shift+F9) para verificar que el bug está resuelto.
10.8.8 Diagrama del flujo de trabajo
flowchart TD
A["1. Reproducir el bug"] --> B["2. Localizar zona sospechosa"]
B --> C["3. Poner breakpoints"]
C --> D["4. Depurar (Shift+F9)"]
D --> E["5. Inspeccionar variables"]
E --> F["6. Step Over (F8) línea a línea"]
F --> G{"¿Valor inesperado?"}
G -->|"Sí"| H["7. Esa línea es la culpable"]
G -->|"No"| F
H --> I{"¿Llama a un método?"}
I -->|"Sí"| J["Step Into (F7) y repite 5-6"]
I -->|"No"| K["8. Detener (Ctrl+F2)"]
J --> K
K --> L["9. Corregir el código"]
L --> M["10. Ejecutar para verificar"]
10.9 Trampas comunes en la depuración
10.9.1 Trampa 1: Step Into en métodos del API
Si haces Step Into en Integer.parseInt, IO.readln o cualquier método del API de Java, te meterás en código que no es tuyo y que no te interesa. Usa Step Over (F8) para métodos del API.
Solución: reserva Step Into para métodos que tú has escrito (en UD4 verás cómo crearlos).
10.9.2 Trampa 2: Olvidar quitar breakpoints
Si dejas breakpoints puestos y ejecutas con Run (Shift+F10), no pasa nada: el programa corre normal. Pero si ejecutas con Debug (Shift+F9), se detendrá en los breakpoints viejos y no entenderás por qué.
Solución: cuando termines de depurar, revisa los breakpoints (clic en el punto rojo para quitarlo) o usa el botón Mute Breakpoints (el icono con dos rayas grises) para desactivarlos todos temporalmente.
10.9.3 Trampa 3: Depurar sin saber qué buscas
Depurar sin un plan es como buscar una aguja en un pajar a ciegas. Antes de pulsar Shift+F9, piensa: "¿Qué valor espero en esta variable? ¿Qué valor veo?" Si no sabes qué esperas, no sabrás si lo que ves es correcto o no.
Solución: antes de depurar, escribe en un papel lo que esperas que valga cada variable. Compara con lo que el depurador te muestra.
10.9.4 Trampa 4: Bucles con muchas iteraciones
Si pones un breakpoint normal dentro de un bucle de 1000 iteraciones, tendrás que pulsar F9 (Resume) 1000 veces para llegar al final. Impracticable.
Solución: usa breakpoints condicionales (i == 500) para detener solo en la iteración que te interesa.
10.9.5 Trampa 5: Confundir Step Over y Step Into
| Quieres... | Usas... |
|---|---|
| Avanzar a la siguiente línea sin entrar en métodos. | Step Over (F8) |
| Entrar dentro de un método que tú escribiste. | Step Into (F7) |
| Salir del método actual. | Step Out (Shift+F8) |
Memoriza esta tabla. Es el 90 % de lo que necesitas saber del depurador.
10.9.6 Resumen de trampas
| Trampa | Síntoma | Solución |
|---|---|---|
| Step Into en API | Te pierdes en código de Java. | Usar Step Over (F8) para métodos del API. |
| Olvidar breakpoints | El programa se detiene sin razón aparente. | Revisar o silenciar breakpoints al terminar. |
| Depurar sin plan | No sabes si lo que ves es correcto. | Escribir lo que esperas antes de depurar. |
| Bucles largos | Muchas iteraciones, imposible parar. | Breakpoints condicionales. |
| Confundir Step Over/Into | Entras donde no querías o no entras donde querías. | Memorizar la tabla de 10.9.5. |
10.10 Ejemplos resueltos: depurar programas con bugs
Vamos a ver tres programas con bugs y cómo encontrarlos con el depurador.
10.10.1 Ejemplo 1: suma incorrecta
Programa con bug:
Síntoma: el programa se cae con ArrayIndexOutOfBoundsException en algún momento.
Depuración:
- Reproducir: ejecutar con
Shift+F10y ver el error en la consola. - Localizar: el error está en el bucle. Pon un breakpoint en la línea
suma = suma + numeros[i];. - Depurar (
Shift+F9): el programa se detiene en la primera iteración. Variables:i = 0,suma = 0,numeros = {10, 20, 30, 40, 50}. Todo correcto. - Step Over (
F8) varias veces:isube a 1, 2, 3, 4.sumasube a 10, 30, 60, 100, 150. Todo correcto hasta aquí. - Step Over una vez más:
isube a 5. La condicióni <= numeros.lengthes5 <= 5=true, así que entra al cuerpo.numeros[5]→ ¡ArrayIndexOutOfBoundsException!. - Encontrado: el bug es
<=en vez de<en elfor. La trampa nº 1 con arrays. - Corregir: cambiar
i <= numeros.lengthpori < numeros.length.
10.10.2 Ejemplo 2: máximo incorrecto
Programa con bug:
Síntoma: el programa dice "El máximo es: 9" — parece correcto, pero si cambiamos el array a {-5, -8, -3, -9, -2}, diría "El máximo es: 0" (incorrecto, debería ser -2).
Depuración:
- Reproducir: cambiar el array a
{-5, -8, -3, -9, -2}y ejecutar. El resultado es 0, que es incorrecto. - Localizar: el bug está en la inicialización de
max. Pon un breakpoint enint max = 0;. - Depurar (
Shift+F9): Variables:max = 0,numeros = {-5, -8, -3, -9, -2}. - Step Over (
F8) en el bucle: en cada iteración,numeros[i] > maxevalúa-5 > 0,-8 > 0, etc. → todofalse.maxnunca cambia, se queda en0. - Encontrado: el bug es
max = 0en vez demax = numeros[0]. Con 0 como inicial, ningún número negativo supera 0. - Corregir: cambiar
int max = 0;porint max = numeros[0];(y empezar el bucle eni = 1).
10.10.3 Ejemplo 3: bucle que no termina
Programa con bug:
Síntoma: el programa se queda colgado. Nunca imprime nada.
Depuración:
- Reproducir: ejecutar con
Shift+F10y ver que se cuelga. Detener conCtrl+F2(o el botón Stop). - Localizar: el bug está en el bucle. Pon un breakpoint en la línea
suma = suma + i;. - Depurar (
Shift+F9): el programa se detiene. Variables:i = 0,suma = 0. - Step Over (
F8):suma = 0 + 0 = 0. La línea siguiente es el}del while, que vuelve arriba. - Step Over otra vez:
isigue siendo0.sumasigue siendo0. El bucle repite sin avanzar. - Encontrado: falta
i++dentro del bucle.inunca cambia, la condicióni < 10siempre estrue. - Corregir: añadir
i++;dentro del bucle.
10.11 Buenas prácticas de depuración
10.11.1 Las 8 reglas del depurador profesional
- Reproduce el bug antes de depurar: sin reproducción, no hay depuración.
- Ten un plan: escribe qué esperas que valgan las variables antes de empezar.
- Pon breakpoints en la zona sospechosa, no por todo el programa.
- Step Over (
F8) por defecto, Step Into (F7) solo para tus métodos. - Breakpoints condicionales para bucles con muchas iteraciones.
- Evaluate Expression (
Alt+F8) para probar expresiones sin modificar el código. - Limpia los breakpoints cuando termines (o silencia con Mute Breakpoints).
- Corrige y vuelve a probar: un bug corregido no es un bug resuelto hasta que lo has verificado.
10.11.2 Cuándo usar Run vs. Debug
| Situación | Usa |
|---|---|
| El programa funciona y quieres ver el resultado. | Run (Shift+F10) |
| El programa no funciona y quieres investigar. | Debug (Shift+F9) |
| Quieres entender cómo fluye un código. | Debug (Shift+F9) |
| Quiero ver si una corrección funciona. | Run (Shift+F10), o Debug si sigue fallando. |
| Tengo un bucle infinito. | Debug (Shift+F9) con un breakpoint en el bucle. |
10.11.3 No abuses del depurador
El depurador es potente, pero no es la única herramienta. A veces lo mejor es:
- Leer el código con calma: muchos bugs se ven a simple vista si lees despacio.
- Imprimir con
IO.println: para bugs simples, unIO.println("llegué aquí, i = " + i)es suficiente. - Pensar antes de pulsar teclas: el 50 % de los bugs se resuelven pensando, no depurando.
Regla del profesor:
El depurador es como un microscopio: potente, pero no lo uses para todo. Si el bug es "se me olvidó un
;", el compilador te lo dice. Si es "no inicialicé una variable", leer el código basta. El depurador brilla cuando el bug es lógico (el programa hace algo distinto a lo que esperas) y no sabes dónde está.
10.12 Resumen y mapa conceptual
10.12.1 Mapa conceptual
mindmap
root((Sección 10 - Depuración IntelliJ))
Ejecutar vs Depurar
Run Shift+F10
Debug Shift+F9
Run para probar
Debug para investigar
Breakpoints
Clic en margen izquierdo
Punto rojo
Múltiples breakpoints
Condicionales con condition
Controles
Step Over F8 no entra en métodos
Step Into F7 entra en métodos
Step Out Shift+F8 sale del método
Resume F9 continúa
Stop Ctrl+F2 detiene
Ventanas
Variables todas las variables
Watches expresiones personalizadas
Console salida y entrada
Frames pila de llamadas
Evaluate Expression
Alt+F8
Probar expresiones
Sin modificar el código
Flujo de trabajo
1 reproducir el bug
2 localizar zona
3 poner breakpoints
4 depurar
5 inspeccionar
6 step over línea a línea
7 corregir
Trampas
Step Into en API
Olvidar breakpoints
Depurar sin plan
Bucles largos
Confundir Over e Into
10.12.2 Las 10 ideas que no debes olvidar
- Run (
Shift+F10) ejecuta sin parar; Debug (Shift+F9) detiene en breakpoints. - Un breakpoint se pone con clic en el margen izquierdo: aparece un punto rojo.
- Step Over (
F8) es el control que más vas a usar: avanza una línea sin entrar en métodos. - Step Into (
F7) entra dentro de un método que tú escribiste. No lo uses en métodos del API. - Step Out (
Shift+F8) sale del método actual y vuelve al llamador. - Resume (
F9) continúa hasta el siguiente breakpoint. - La ventana Variables muestra todas las variables accesibles; la ventana Watches muestra expresiones que tú eliges.
- Evaluate Expression (
Alt+F8) te permite evaluar cualquier expresión Java en el punto de parada. - Breakpoints condicionales se detienen solo cuando se cumple una condición (
i == 500,numeros[i] < 0). - El flujo de trabajo es: reproducir → localizar → depurar → inspeccionar → step over → encontrar → corregir → verificar.
10.12.3 Glosario rápido
| Término | Significado |
|---|---|
| Depuración (debugging) | Proceso de encontrar y corregir errores en un programa. |
| Depurador (debugger) | Herramienta que permite ejecutar un programa paso a paso e inspeccionar su estado. |
| Breakpoint | Punto de interrupción: marca en una línea donde el programa se detiene al depurar. |
| Breakpoint condicional | Breakpoint que se activa solo cuando se cumple una condición. |
Step Over (F8) |
Ejecuta la línea actual sin entrar en métodos. |
Step Into (F7) |
Entra dentro del método de la línea actual. |
Step Out (Shift+F8) |
Sale del método actual y vuelve al llamador. |
Resume (F9) |
Continúa la ejecución hasta el siguiente breakpoint. |
Stop (Ctrl+F2) |
Detiene el programa y la depuración. |
| Ventana Variables | Muestra todas las variables accesibles con sus valores actuales. |
| Ventana Watches | Muestra expresiones personalizadas que tú eliges vigilar. |
| Ventana Frames | Muestra la pila de llamadas (qué método llamó a qué). |
Evaluate Expression (Alt+F8) |
Permite evaluar cualquier expresión Java en el punto de parada. |
Run (Shift+F10) |
Ejecuta el programa sin depuración. |
Debug (Shift+F9) |
Ejecuta el programa con depuración (se detiene en breakpoints). |
| Mute Breakpoints | Desactiva todos los breakpoints temporalmente. |
| Bug | Error en el programa que hace que se comporte de forma incorrecta. |
| Call stack (pila de llamadas) | Lista de métodos en ejecución, desde el más interno hasta main. |
10.13 Actividades propuestas
Cinco actividades graduadas. Hazlas en orden. Las soluciones se publicarán en Aules.
10.13.1 Actividad 1 — Depurar el "suma incorrecta"
Objetivo: practicar el flujo de depuración con un bug de off-by-one.
Enunciado: Crea el siguiente programa (con un bug intencionado):
Tareas:
- Ejecuta con
Shift+F10y observa el error en la consola. - Pon un breakpoint en la línea
suma = suma + numeros[i];. - Depura con
Shift+F9. - Usa
F8(Step Over) repetidamente y observa cómo cambianiysuma. - Identifica en qué iteración salta el error y por qué.
- Corrige el bug y verifica con
Shift+F10.
Entrega: archivo SumaBuggy.java (corregido) en el paquete jams.programacion.ud3, con un comentario al final explicando qué era el bug y cómo lo encontraste con el depurador.
Criterios evaluados: CE 3.6, CE 3.7.
10.13.2 Actividad 2 — Depurar el "máximo incorrecto"
Objetivo: practicar la inspección de variables para encontrar un bug lógico.
Enunciado: Crea el siguiente programa (con un bug intencionado):
Tareas:
- Ejecuta con
Shift+F10y observa el resultado (dirá "El máximo es: 0", que es incorrecto). - Pon un breakpoint en la línea
if (numeros[i] > max). - Depura con
Shift+F9. - Usa
F8(Step Over) y observa el valor denumeros[i]ymaxen cada iteración. - Usa
Alt+F8(Evaluate Expression) para evaluarnumeros[i] > maxen cada paso. ¿Por qué siempre esfalse? - Identifica el bug y corrídelo.
- Verifica con
Shift+F10.
Entrega: archivo MaximoBuggy.java (corregido) en el paquete jams.programacion.ud3, con un comentario al final explicando el bug.
Criterios evaluados: CE 3.6, CE 3.7.
10.13.3 Actividad 3 — Depurar con breakpoint condicional
Objetivo: practicar breakpoints condicionales en un bucle largo.
Enunciado: Crea el siguiente programa, que suma los números del 1 al 1000 pero tiene un bug en la iteración 743 (la suma salta de 276.281 a 277.281 en vez de a 276.282):
Tareas:
- Ejecuta con
Shift+F10y observa que el resultado no coincide con el esperado. - Pon un breakpoint condicional en la línea
suma = suma + i + 1000;con la condicióni == 743. - Depura con
Shift+F9. El programa debería detenerse solo en la iteración 743. - Inspecciona
i,sumaantes y después de la línea. - Identifica el bug (el
+1000extra) y corrídelo. - Verifica con
Shift+F10.
Entrega: archivo SumaMilBuggy.java (corregido) en el paquete jams.programacion.ud3, con un comentario al final explicando cómo usaste el breakpoint condicional.
Criterios evaluados: CE 3.6, CE 3.7.
10.13.4 Actividad 4 — Depurar un bucle infinito
Objetivo: practicar la depuración de un bucle que no termina.
Enunciado: Crea el siguiente programa (con un bug intencionado):
Tareas:
- Ejecuta con
Shift+F10y observa que el programa se cuelga. Detén conCtrl+F2. - Pon un breakpoint en la línea
suma = suma + i;. - Depura con
Shift+F9. - Usa
F8(Step Over) varias veces y observa qué variable no cambia. - Identifica qué falta (el
i++) y corrídelo. - Verifica con
Shift+F10.
Entrega: archivo BucleInfinito.java (corregido) en el paquete jams.programacion.ud3, con un comentario al final explicando el bug.
Criterios evaluados: CE 3.6, CE 3.7.
10.13.5 Actividad 5 — Cuestionario de repaso
Responde por escrito:
- ¿Cuál es la diferencia entre Run (
Shift+F10) y Debug (Shift+F9)? - ¿Cómo pones un breakpoint? ¿Cómo lo quitas?
- ¿Qué hace Step Over (
F8)? ¿En qué se diferencia de Step Into (F7)? - ¿Cuándo usarías Step Into (
F7) y cuándo NO? - ¿Qué hace Step Out (
Shift+F8)? - ¿Qué hace Resume (
F9)? - ¿Qué muestra la ventana Variables? ¿Y la ventana Watches?
- ¿Para qué sirve Evaluate Expression (
Alt+F8)? Pon un ejemplo de uso. - ¿Qué es un breakpoint condicional y por qué es útil en bucles largos?
- Describe los 7 pasos del flujo de trabajo para encontrar un bug.
- ¿Por qué no debes hacer Step Into en
Integer.parseIntoIO.readln? - ¿Qué haces cuando terminas de depurar: dejas los breakpoints puestos o los quitas? ¿Por qué?
Entrega: archivo cuestionario_seccion10.md con tus respuestas.
Criterios evaluados: CE 3.6, CE 3.7.
10.14 Lo que NO hemos visto (y dónde verlo)
Esta sección te ha enseñado la depuración básica con IntelliJ IDEA: breakpoints, controles Step Over/Into/Out/Resume, ventanas Variables/Watches, Evaluate Expression y breakpoints condicionales. Hay cosas relacionadas que se reservan para secciones/unidades posteriores:
| Concepto | ¿Por qué no aquí? | ¿Dónde se ve? |
|---|---|---|
assert y aserciones |
Alternativa a excepciones para contratos internos. | Sección 11 de UD3. |
| Testing con JUnit | Framework de testing; necesita Maven y dependencias externas. | UD2 (intro), UD4 (profundización). |
| Profiling y análisis de rendimiento | Análisis de CPU/memoria; avanzado. | Fuera del módulo. |
| Debugging remoto | Depurar programas en otro equipo; avanzado. | Fuera del módulo. |
| Drop Frame (rebobinar la ejecución) | Característica avanzada del depurador. | Profesional, fuera del módulo. |
| Breakpoints de método | Se detienen al entrar/salir de un método. Necesita métodos propios. | UD4. |
| Breakpoints de excepción | Se detienen cuando se lanza una excepción específica. | Profesional. |
Logging en vez de IO.println |
Framework de logging (SLF4J, Logback). | UD5 / profesional. |
10.15 Lo que viene en la sección 11
Con esta sección ya dominas el depurador de IntelliJ. Es una de las herramientas más importantes que aprenderás en todo el ciclo: te va a acompañar en cada programa que escribas a partir de ahora.
En la sección 11 verás assert y aserciones, una herramienta complementaria al depurador: mientras el depurador te permite investigar un bug cuando ocurre, las aserciones te permiten detectar automáticamente si se viola una condición que debería ser cierta. Es como tener un "alarma" que suena si algo inesperado pasa durante la ejecución.
Aprenderás:
- Sintaxis de
assert:assert condicion;yassert condicion : "mensaje";. - Cómo activar las aserciones con el flag
-eade la JVM. - Diferencia entre
asserty excepciones:assertes para contratos internos (cosas que el programador sabe que deben ser ciertas), las excepciones son para errores esperados (cosas que el usuario puede provocar). - Precondiciones y postcondiciones de métodos.
- Cuándo usar
asserty cuándo no.
Cuando termines la sección 11, habrás cubierto todo el bloque de detección y corrección de errores de UD3. Después, en la sección 12 verás el test (cuestionarios de repaso) y en la 13 los ejercicios integradores que cierran la unidad.
Cierre del profesor. Llegar hasta aquí es mérito. Acabas de aprender la herramienta que va a cambiar tu forma de programar para siempre. El depurador no es un lujo: es una necesidad. Sin él, estás a ciegas; con él, ves dentro del programa como con rayos X. La regla más importante que te llevas de esta sección es: Step Over (
F8) por defecto, Step Into (F7) solo para tus métodos, y breakpoints condicionales para bucles largos. Si interiorizas eso, vas a depurar como un profesional. Nos vemos en la sección 11, donde verásassert, una herramienta más ligera que el depurador para detectar bugs automáticamente mientras el programa corre.