Programmation Java

Classe SDA 7 2025-2026

Module 6

La Gestion des Exceptions

Anticiper l'Inattendu et Écrire du Code Robuste

1. Pourquoi Gérer les Exceptions ?

Jusqu'à présent, nos programmes fonctionnent bien dans un monde parfait. Mais que se passe-t-il si :

Sans gestion des exceptions, le programme s'arrête brutalement en affichant une erreur rouge dans la console. C'est une mauvaise expérience pour l'utilisateur. La gestion des exceptions est un filet de sécurité qui nous permet d'attraper ces erreurs et de réagir de manière contrôlée.

Analogie : Conduire une Voiture

Vous ne vous attendez pas à avoir un pneu crevé, mais vous avez une roue de secours (bloc catch) au cas où. Le bloc try est le trajet normal, et le bloc finally serait de toujours détacher votre ceinture de sécurité, que le trajet se soit bien passé ou non.

Les Blocs try, catch et finally : Le Filet de Sécurité

C'est le mécanisme central de la gestion d'erreurs en Java.

→ try

On place dans ce bloc le code à risque, celui qui pourrait provoquer une erreur (une "exception").

→ catch

Ce bloc est le plan de secours. Il ne s'exécute que si une exception du type spécifié se produit dans le bloc try. Il "attrape" l'erreur et exécute un code de gestion.

→ finally

Ce bloc est toujours exécuté, qu'une erreur se soit produite ou non. C'est l'endroit idéal pour nettoyer les ressources (comme fermer un fichier ou un Scanner), garantissant que cela soit fait quoi qu'il arrive.

Exemple 1 : Gérer une Saisie Utilisateur Incorrecte

InputMismatchException est une erreur courante qui survient lorsque l'utilisateur tape "abc" alors que le programme attendait un nombre.

import java.util.InputMismatchException; import java.util.Scanner; public class ExceptionHandling { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); try { // Zone à risque : l'utilisateur pourrait ne pas entrer un nombre System.out.print("Entrez un nombre entier : "); int number = scanner.nextInt(); System.out.println("Vous avez entré : " + number); } catch (InputMismatchException e) { // Plan de secours System.out.println("Erreur : L'entrée n'est pas un nombre entier valide."); } finally { // Nettoyage : toujours exécuté scanner.close(); System.out.println("Le programme est terminé."); } } }
Testez ce Code

Lancez-le une fois en entrant 10, puis une autre fois en entrant texte. Vous verrez les différents chemins d'exécution.

Exemple 2 : Gérer Plusieurs Types d'Exceptions

Un bloc try peut générer plusieurs types d'erreurs. Vous pouvez chaîner les blocs catch pour réagir différemment à chaque type d'erreur. Les catch sont évalués dans l'ordre, du plus spécifique au plus général.

public class MultipleExceptions { public static void main(String[] args) { try { int[] numbers = {1, 2, 3}; int a = 10; int b = 0; // Modifier cette valeur pour tester // Ligne pouvant générer une ArithmeticException System.out.println("Résultat : " + (a / b)); // Ligne pouvant générer une ArrayIndexOutOfBoundsException System.out.println("Valeur : " + numbers[5]); } catch (ArithmeticException e) { // Gère spécifiquement la division par zéro System.out.println("Erreur : Division par zéro impossible."); } catch (ArrayIndexOutOfBoundsException e) { // Gère spécifiquement un accès hors des limites System.out.println("Erreur : L'indice est hors des limites."); } catch (Exception e) { // Le "catch-all" : attrape toute autre erreur imprévue System.out.println("Erreur inattendue : " + e.getMessage()); } } }
Important : Toujours ordonner les blocs catch du plus spécifique au plus général. Si vous commencez par catch (Exception e), tous les autres blocs catch seront jamais atteints !

Pour aller plus loin :

Source: EvoluNoob

2. Créer et Lancer ses Propres Exceptions

Parfois, les exceptions de base de Java ne suffisent pas. Vous pouvez vouloir créer des erreurs spécifiques à la logique de votre application (par exemple, un solde de compte bancaire ne peut pas être négatif).

Les Trois Étapes

1. Créer une classe d'exception personnalisée

On crée une classe qui hérite de Exception.

2. Lancer l'exception

Dans votre code, si une condition d'erreur est remplie, vous utilisez le mot-clé throw new pour "lancer" une instance de votre exception.

3. Déclarer l'exception

Une méthode qui peut lancer une exception "checked" doit le déclarer dans sa signature avec le mot-clé throws.

Exemple 3 : Créer une Exception InvalidAgeException

// 1. Création de notre propre type d'erreur class InvalidAgeException extends Exception { public InvalidAgeException(String message) { super(message); // Appelle le constructeur de Exception } } public class CustomExceptionExample { // 2. Cette méthode déclare qu'elle peut potentiellement lancer notre erreur public static void checkAge(int age) throws InvalidAgeException { if (age < 18) { // 3. On lance l'exception si la condition est remplie throw new InvalidAgeException( "L'âge doit être >= 18 ans pour s'inscrire." ); } else { System.out.println("Inscription validée !"); } } public static void main(String[] args) { try { checkAge(25); // Cas valide checkAge(15); // Cas invalide qui va déclencher l'exception } catch (InvalidAgeException e) { // On attrape notre exception personnalisée System.out.println("Erreur : " + e.getMessage()); } } }

Résultat :

Inscription validée ! Erreur : L'âge doit être >= 18 ans pour s'inscrire.
Pourquoi des Exceptions Personnalisées ?

Créer des exceptions personnalisées rend votre code beaucoup plus lisible et spécifique aux règles de votre domaine (finance, jeux, etc.). Cela facilite également la maintenance et la compréhension du code par d'autres développeurs.

Exemple 4 : Exception Personnalisée pour un Compte Bancaire

class InsufficientFundsException extends Exception { public InsufficientFundsException(String message) { super(message); } } class BankAccount { private double balance; public BankAccount(double initialBalance) { this.balance = initialBalance; } public void withdraw(double amount) throws InsufficientFundsException { if (amount > balance) { throw new InsufficientFundsException( "Solde insuffisant. Vous avez " + balance + " €, vous tentez de retirer " + amount + " €." ); } balance -= amount; System.out.println("Retrait de " + amount + " € effectué."); } } public class BankingExample { public static void main(String[] args) { BankAccount account = new BankAccount(500); try { account.withdraw(200); // OK account.withdraw(400); // Erreur ! } catch (InsufficientFundsException e) { System.out.println("Erreur bancaire : " + e.getMessage()); } } }

Résultat :

Retrait de 200.0 € effectué. Erreur bancaire : Solde insuffisant. Vous avez 300.0 €, vous tentez de retirer 400.0 €.

Résumé : Les Meilleures Pratiques

Pratique Description
Toujours utiliser try-catch Pour tout code qui pourrait générer une exception
Ordonnancer les catch Du plus spécifique au plus général
Utiliser finally Pour nettoyer les ressources (fichiers, Scanner, etc.)
Créer des exceptions personnalisées Pour les erreurs spécifiques à votre domaine
Ne pas ignorer les exceptions Un bloc catch vide rend le debugging difficile
À Retenir

La gestion des exceptions ne sert pas à "cacher" les erreurs, mais à les gérer correctement et à permettre au programme de continuer son exécution de manière contrôlée. Un bon programme anticipe les problèmes et y répond de manière élégante.

Exercices Pratiques : Bâtir des Programmes Robustes

Mettez en pratique la gestion des exceptions pour rendre vos programmes plus fiables et capables de gérer les situations inattendues.

Exercice 1 : Conversion d'Âge Sécurisée

Écrivez un programme qui demande à l'utilisateur son année de naissance (sous forme de texte) et calcule son âge approximatif en 2025. Le programme doit gérer le cas où l'utilisateur entre du texte qui n'est pas un nombre (ex: "deux mille").

Indice : Placez l'appel à Integer.parseInt() à l'intérieur d'un bloc try et attrapez l'exception NumberFormatException.

Voir la solution
import java.util.Scanner; public class AgeConverter { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Veuillez entrer votre année de naissance : "); String input = scanner.nextLine(); try { // Tentative de conversion de la chaîne en entier int anneeNaissance = Integer.parseInt(input); int age = 2025 - anneeNaissance; System.out.println("Vous aurez environ " + age + " ans en 2025."); } catch (NumberFormatException e) { // Si la conversion échoue System.out.println("Erreur : L'entrée n'est pas une année valide. Veuillez entrer un nombre."); } finally { scanner.close(); } } }

Exercice 2 : Calculatrice Sécurisée (Division)

Créez une petite calculatrice qui demande deux nombres entiers à l'utilisateur et affiche le résultat de leur division. Votre programme doit gérer deux types d'erreurs :

  • L'utilisateur entre du texte au lieu de nombres (InputMismatchException).
  • L'utilisateur tente de diviser par zéro (ArithmeticException).

Indice : Vous aurez besoin d'un bloc try suivi de deux blocs catch distincts, un pour chaque type d'exception.

Voir la solution
import java.util.InputMismatchException; import java.util.Scanner; public class SafeCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); try { System.out.print("Entrez le numérateur (entier) : "); int numerateur = scanner.nextInt(); System.out.print("Entrez le dénominateur (entier) : "); int denominateur = scanner.nextInt(); double resultat = (double) numerateur / denominateur; System.out.println("Le résultat de la division est : " + resultat); } catch (InputMismatchException e) { System.out.println("Erreur : Vous devez entrer des nombres entiers."); } catch (ArithmeticException e) { System.out.println("Erreur : La division par zéro est impossible."); } finally { scanner.close(); System.out.println("Calcul terminé."); } } }

Exercice 3 : Exception Personnalisée pour un Mot de Passe

Créez une exception personnalisée nommée PasswordTooShortException. Écrivez ensuite une méthode verifierMotDePasse(String mdp) qui lance cette exception si le mot de passe fourni a moins de 8 caractères. Dans votre main, appelez cette méthode dans un bloc try-catch pour tester un mot de passe valide et un mot de passe trop court.

Indice : Votre classe d'exception doit hériter de Exception. Votre méthode utilisera if (mdp.length() < 8) { throw new ... } et devra déclarer throws PasswordTooShortException dans sa signature.

Voir la solution
// 1. Créer l'exception personnalisée class PasswordTooShortException extends Exception { public PasswordTooShortException(String message) { super(message); } } public class PasswordValidator { // 2. Créer la méthode qui lance l'exception public static void verifierMotDePasse(String mdp) throws PasswordTooShortException { if (mdp.length() < 8) { throw new PasswordTooShortException("Le mot de passe doit contenir au moins 8 caractères."); } else { System.out.println("Mot de passe valide !"); } } public static void main(String[] args) { // 3. Tester la méthode dans un bloc try-catch try { System.out.println("Test avec 'motdepasse123'..."); verifierMotDePasse("motdepasse123"); // Valide System.out.println("\nTest avec 'court'..."); verifierMotDePasse("court"); // Invalide, va lancer l'exception } catch (PasswordTooShortException e) { System.out.println("Erreur de validation : " + e.getMessage()); } } }