Aller au contenu principal

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 debugDébogueur
Modifier le code pour ajouter des printPas de modification du code
Relancer à chaque modificationPause au bon endroit
Ne voit que les valeurs explicitement affichéesVoit toutes les variables
Difficile sur des boucles longuesBreakpoint 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

ActionRaccourciDescription
Step OverF8Exécuter la ligne courante et passer à la suivante
Step IntoF7Entrer dans la méthode appelée sur la ligne courante
Step OutShift+F8Finir la méthode courante et revenir à l'appelant
ResumeF9Continuer jusqu'au prochain breakpoint
StopArrêter le programme
info

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 :

  1. Poser un breakpoint sur int degats = ...
  2. Lancer en Debug (Shift+F9)
  3. Observer dans Variables : attaquant.force diminue alors qu'il devrait rester stable
  4. Step Over (F8) plusieurs fois pour confirmer
  5. Evaluate Expression : defenseur.getForce() → valeur inchangée = le bug est confirmé
  6. Corriger : attaquant.subirDegats(degats)defenseur.subirDegats(degats)

Test de mémorisation/compréhension


Comment ajouter un breakpoint dans IntelliJ IDEA ?


Quel raccourci lance le programme en mode Debug ?


Que fait Step Over (F8) ?


Quel raccourci ouvre Evaluate Expression ?


À quoi sert un breakpoint conditionnel ?


Quelle fonctionnalité permet de stopper automatiquement sur une NullPointerException ?


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;
}
}
}

Bonne pratique - Observer les variables, pas seulement le code

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.


Bonne pratique - Breakpoint conditionnel pour les boucles longues

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.


Bonne pratique - Evaluate Expression pour tester une hypothèse sans recompiler

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.

📌 Une solution