Débogage avec IntelliJ IDEA
System.out.println() pour déboguer, c'est lent et bruyant. Le débogueur d'IntelliJ IDEA vous permet de stopper l'exécution, inspecter toutes les variables et avancer ligne par ligne — sans modifier votre code.
Notions théoriques
Pourquoi un vrai débogueur ?
Avec println, vous ne voyez que ce que vous avez pensé à afficher. Avec le débogueur, vous voyez tout : toutes les variables, toutes les valeurs, à n'importe quel endroit.
| println debug | Débogueur |
|---|---|
Modifier le code pour ajouter des print | Pas de modification du code |
| Relancer à chaque modification | Pause au bon endroit |
| Ne voit que les valeurs explicitement affichées | Voit toutes les variables |
| Difficile sur des boucles longues | Breakpoint conditionnel : pause uniquement quand i == 50 |
Point d'arrêt (Breakpoint)
Un point d'arrêt est une marque sur une ligne de code. Quand le programme arrive à cette ligne, il se met en pause.
Ajouter un breakpoint : cliquer sur le numéro de ligne dans la marge gauche d'IntelliJ. Un cercle rouge apparaît.
Supprimer un breakpoint : recliquer sur le cercle rouge.
Lancer en mode Debug
Deux façons :
- Raccourci : Shift+F9 (ou le bouton insecte vert dans la barre d'outils)
- Clic droit sur la méthode
main()→ Debug 'Main.main()'
Le programme s'exécute normalement jusqu'au premier breakpoint, puis se met en pause.
Contrôles de débogage
| Action | Raccourci | Description |
|---|---|---|
| Step Over | F8 | Exécuter la ligne courante et passer à la suivante |
| Step Into | F7 | Entrer dans la méthode appelée sur la ligne courante |
| Step Out | Shift+F8 | Finir la méthode courante et revenir à l'appelant |
| Resume | F9 | Continuer jusqu'au prochain breakpoint |
| Stop | — | Arrêter le programme |
Step Over est le plus utilisé : il avance ligne par ligne sans entrer dans les méthodes. Utilisez Step Into uniquement quand vous voulez déboguer l'intérieur d'une méthode spécifique.
Fenêtre Variables
La fenêtre Variables (en bas à gauche en mode Debug) affiche toutes les variables locales et leurs valeurs au moment de la pause.
Vous pouvez :
- développer un objet (cliquer sur la flèche) pour voir tous ses attributs
- modifier une valeur (double-clic sur la valeur) pour tester une hypothèse sans recompiler
Evaluate Expression
Alt+F8 (ou clic droit → Evaluate Expression) ouvre un champ dans lequel vous pouvez taper n'importe quelle expression Java et voir son résultat immédiatement.
// Exemples d'expressions à évaluer
personnages.size()
guerrier.getForce() * 2
personnages.stream().filter(p -> p.getForce() > 100).count()
C'est particulièrement utile pour tester une correction sans redémarrer le programme.
Breakpoint conditionnel
Un breakpoint conditionnel ne stoppe le programme que si une condition est vraie. Idéal pour les boucles longues.
Configuration : clic droit sur le cercle rouge du breakpoint → Edit Breakpoint → entrer la condition.
// Dans une boucle de 1000 itérations, s'arrêter uniquement quand i == 500
for (int i = 0; i < personnages.size(); i++) {
// Breakpoint conditionnel : i == 500
Personnage p = personnages.get(i);
combattre(p);
}
Watch — Surveiller une expression
Un Watch est une expression que vous voulez observer en permanence pendant le débogage. Elle est recalculée à chaque step.
Dans la fenêtre Variables, cliquez sur le + pour ajouter un Watch :
guerrier.getForce()
personnages.size()
Exception Breakpoint
Vous pouvez configurer IntelliJ pour stopper automatiquement quand une exception est levée, même sans breakpoint sur la ligne.
Run → View Breakpoints → + → Java Exception Breakpoints → NullPointerException
Le programme se met en pause exactement à la ligne qui a levé l'exception, avec toutes les variables visibles.
Exemple pratique
public class Combat {
public void derouler(Personnage attaquant, Personnage defenseur) {
int round = 1;
while (defenseur.getForce() > 0 && attaquant.getForce() > 0) {
// Breakpoint ici pour inspecter chaque round
int degats = attaquant.attaquer() - defenseur.getDefense();
degats = Math.max(0, degats);
// Bug intentionnel : les rôles sont inversés
// On réduit la force de l'attaquant au lieu du défenseur !
attaquant.subirDegats(degats); // BUG : devrait être defenseur
System.out.println("Round " + round + " : " + degats + " dégâts");
round++;
if (round > 100) break; // sécurité anti-boucle infinie
}
}
}
Session de débogage :
- Poser un breakpoint sur
int degats = ... - Lancer en Debug (Shift+F9)
- Observer dans Variables :
attaquant.forcediminue alors qu'il devrait rester stable - Step Over (F8) plusieurs fois pour confirmer
- Evaluate Expression :
defenseur.getForce()→ valeur inchangée = le bug est confirmé - Corriger :
attaquant.subirDegats(degats)→defenseur.subirDegats(degats)
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Vous allez déboguer un bug intentionnel dans la boucle de combat RPG.
Étape 1 — Identifier le bug avec un breakpoint
Le code suivant contient un bug : après plusieurs rounds, c'est l'attaquant qui perd de la force au lieu du défenseur. Posez un breakpoint pour observer le problème.
public class Combat {
public void derouler(Personnage attaquant, Personnage defenseur) {
int round = 1;
while (defenseur.getForce() > 0 && attaquant.getForce() > 0) {
int degats = attaquant.attaquer() - defenseur.getDefense();
degats = Math.max(0, degats);
attaquant.subirDegats(degats); // BUG ICI
System.out.println("Round " + round + " - dégâts: " + degats);
round++;
if (round > 20) break;
}
}
}
Le bug ci-dessus est difficile à repérer à la lecture. Avec le débogueur, il suffit de poser un breakpoint dans la boucle et d'observer pendant 2-3 rounds : attaquant.force diminue → bug trouvé en 30 secondes. Apprenez à lire la fenêtre Variables avant de lire le code.
Étape 2 — Utiliser un breakpoint conditionnel sur la boucle
Le combat dure parfois 50 rounds. Configurez un breakpoint conditionnel pour ne s'arrêter qu'au round 10.
Sur une boucle de 1000 itérations, appuyer sur F9 999 fois pour atteindre l'itération problématique est impraticable. Le breakpoint conditionnel (i == 999, personnage.getForce() < 10) est la solution correcte. Utilisez-le dès que vous soupçonnez un bug à une itération précise.
Étape 3 — Évaluer une expression pendant la pause
En pause sur le breakpoint, utilisez Evaluate Expression (Alt+F8) pour tester la correction avant de modifier le code.
Avant de modifier le code et de relancer, évaluez votre hypothèse dans Evaluate Expression. Vous pouvez même y écrire defenseur.subirDegats(10) pour modifier l'état à la volée et tester l'impact immédiatement. C'est beaucoup plus rapide que modifier → sauvegarder → recompiler → relancer.