Keyboard shortcuts

Touchez ← ou → pour naviguer les chapitres

Touchez S ou / pour chercher dans le livre

Touchez ? pour afficher ce message

Touchez Esc pour masquer ce message

Accueil > Programmer avec Java >

Gérer les exceptions avec try et catch

Survol et attentes

Définitions
Entrée invalide
une entrée qui ne correspond pas à une gamme de valeurs acceptables.
Exception
un Ă©vĂ©nement imprĂ©vu qui cause le plantage d’un programme s’il n’est pas gĂ©rĂ©. Java inclut une classe Exception qui permet de gĂ©rer ces Ă©vĂ©nements en fournissant des informations sur l’erreur qui s’est produite.
try et catch
blocs de code utilisĂ©s pour gĂ©rer les exceptions en Java. Le bloc try contient le code qui pourrait gĂ©nĂ©rer une exception, et le bloc catch contient le code qui gĂšre l’exception si elle se produit.
throws
un mot-clĂ© utilisĂ© dans la signature d’une mĂ©thode pour indiquer qu’elle utilise du code qui peut gĂ©nĂ©rer une exception et ne le gĂšre pas. La mĂ©thode passe ainsi la responsabilitĂ© de gĂ©rer l’exception Ă  la mĂ©thode appelante.
Responsabilité unique
principe de conception de logiciel qui stipule qu’une classe ou une mĂ©thode devrait ĂȘtre responsable d’une seule tĂąche.

Objectifs d’apprentissage

À la fin de cette leçon vous devrez ĂȘtre en mesure de :

  • Identifier les exceptions les plus communes en Java.
  • Savoir qu’elles entrĂ©es peuvent causer des exceptions et les distinguer de celles qui sont invalides pour d’autres raisons.
  • Comprendre la structure d’un bloc try et catch pour gĂ©rer les exceptions.

CritĂšres de succĂšs

  • Je peux gĂ©rer des cas qui causeraient autrement un plantage du programme en utilisant des blocs try et catch.

Responsabilité unique

En gĂ©nie logicielle, il y a un principe qui s’appelle la responsabilitĂ© unique. Ce principe nous dit que chaque mĂ©thode doit ĂȘtre responsable d’une seule chose. C’est une des raisons pourquoi nous brisons nos algorithmes en mĂ©thodes plus petites : cela limite la responsabilitĂ© de main Ă  l’organisation globale des opĂ©rations et permet Ă  chaque mĂ©thode d’avoir un objectif clair.

Si on utilise du code qui peut générer une exception, on a deux choix :

  • ajouter une dĂ©claration throws Exception Ă  la signature de la mĂ©thode pour passer la gestion de l’exception Ă  la mĂ©thode appelante, ou
  • utiliser un bloc try et catch pour gĂ©rer l’exception dans la mĂ©thode directement.

La deuxiĂšme option est prĂ©fĂ©rable selon le principe de responsabilitĂ© unique, car la mĂ©thode gĂšre les problĂšmes potentiels avec le code qu’il utilise pour accomplir sa tĂąche, et les autres mĂ©thodes n’ont pas besoin de s’en soucier : elles peuvent se concentrer sur leur propre tĂąche.

Bloc try et catch pour des entrées invalides

Le bloc try contient le code qui peut lancer une exception, et le bloc catch contient le code Ă  faire si une exception est lancĂ©e. Voici la structure de base d’un bloc try et catch :

try {
    // code qui pourrait lancer une exception
} catch (Exception e) {
    // code à exécuter si une exception est lancée
}

Voici un exemple de code1 qui lance une exception si l’utilisateur entre un texte qui ne peut pas ĂȘtre converti en un nombre entier. Dans cet exemple, on ne laisse pas le programme planter, mais on demande Ă  l’utilisateur de rĂ©essayer :

Fichier: ExceptionExample.java

import java.util.*;

Scanner input = new Scanner(System.in);

int getInt(String prompt) {
    // tentatives infinies jusqu'Ă  ce que tout dans le try fonctionne
    while (true) { 
        try {
            System.out.print(prompt);
            int number = input.nextInt(); // peut planter
            return number; // quitte la méthode si tout va bien
        } catch (Exception e) { // si ça plante
            System.out.println("   Entrée invalide");
            input.next(); // vide l'entrée invalide du Scanner
        }
    }
}

void main() {
    int age = getInt("Entrez votre ùge : "); // pas besoin de savoir que ça peut planter
    System.out.println("Vous avez soumis un Ăąge de : " + age);
}

Notez que dans main on veut simplement obtenir un nombre entier et l’utiliser. Cela est possible parce que la mĂ©thode getInt gĂšre les exceptions qui pourraient survenir lors de la conversion de l’entrĂ©e utilisateur en un nombre entier. Ainsi, chaque mĂ©thode s’occupe de sa propre responsabilitĂ© et n’a pas besoin de connaĂźtre les dĂ©tails internes des autres mĂ©thodes. C’est un bon exemple de la responsabilitĂ© unique.

Voici une autre version de main 1 pour ce mĂȘme problĂšme, mais dans ce cas-ci, main gĂšre une autre sorte d’entrĂ©e invalide : une entrĂ©e qui n’est pas un Ăąge valide. Ce type d’erreur ne cause pas d’exception, mais pourrait causer des erreurs de logique dans le programme.

void main() {
    int age = getInt("Entrez votre Ăąge : ");
    if (age < 0) { // gérer une valeur logiquement invalide
        System.out.println("Âge invalide");
    } else {
        System.out.println("Vous avez soumis un Ăąge de : " + age);
    }
}

Bloc try et catch pour des ressources comme des fichiers

Nous étudions les fichiers en plus de détail dans la derniÚre section de cette unité

Si le programme gĂ©nĂšre une exception lors de l’utilisation d’une ressource comme un fichier, il est important de fermer la ressource avant de quitter le programme. Pour cela, on utilise une dĂ©claration try avec une ressource. Dans cette version de la structure, la ressource est dĂ©clarĂ©e dans les parenthĂšses aprĂšs le mot-clĂ© try. La ressource est automatiquement fermĂ©e par Java Ă  la fin du bloc try, mĂȘme si une exception est lancĂ©e.

Voici la structure d’une dĂ©claration try-catch quand le plantage est liĂ© Ă  la ressource utilisĂ©e :

try ( déclaration de la ressource qui peut planter ) {
    // code à exécuter avec la ressource si ça ne plante pas
} catch (Exception e) {
    // code à exécuter si ça plante
}

Voici un exemple oĂč la ressource qui peut planter est un FileWriter pour Ă©crire dans un fichier.

void writeMessageToFile(String message) {
    try (FileWriter output = new FileWriter("./data/output.txt")) {
        output.write(message);
    } catch (Exception e) {
        System.out.println("Chemin de fichier invalide");
    }
}

Voici un deuxiĂšme exemple oĂč la ressource qui peut planter est l’objet File qu’on passe au Scanner pour extraire son contenu.

String getFileContents(Locale decimalFormat) {
    try (Scanner fileReader = new Scanner(new File("./data/input.txt"))) {
        fileReader.useLocale(decimalFormat);
        fileReader.useDelimiter("\\Z"); // next() s'arrĂȘte au caractĂšre de fin de fichier
        return fileReader.next();
    } catch (Exception e) {
        System.out.println("Fichier introuvable");
        return null; // quittez la méthode avec une référence `null` pour le String
    }
}

Notez que dans ces deux exemples, on doit déclarer et initialiser la ressource plantable entre des parenthÚses aprÚs le mot-clé try.

Exceptions spécifiques

Pour ce cours, c’est tout Ă  fait normal d’utiliser Exception - la plus gĂ©nĂ©rale de toutes les exceptions - comme type d’exception dans le bloc catch. Mais en situation de production logicielle, c’est important de dĂ©clarer l’exception spĂ©cifique qui peut survenir dans le bloc catch.

Par exemple :

  • Dans le cas d’entrĂ©e invalide, le type d’exception qui est lancĂ©e est InputMismatchException (avec les mĂ©thodes de Scanner nextInt et nextDouble) ou NumberFormatException (si on utilise plutĂŽt Integer.parseInt(input.next()) ou Double.parseDouble(input.next())). Ce sont des exceptions pour les erreurs de conversion de chaĂźnes de caractĂšres en nombres.
  • Dans le cas de la lecture ou l’écriture de fichiers, l’exception est IOException.

Utiliser une exception spĂ©cifique permet de gĂ©rer les exceptions de maniĂšre plus prĂ©cise. En fait, cette structure nous permet de dĂ©clarer un bloc catch pour chaque type d’exception qui peut survenir. Le premier bloc catch qui correspond Ă  l’exception lancĂ©e est celui qui est exĂ©cutĂ©, comme une cascade if-else if, alors c’est important de les mettre dans l’ordre du plus spĂ©cifique (p. ex. IOException) au plus gĂ©nĂ©ral (Exception).

Exercices

📚 Tester la comprĂ©hension

aucun quiz de vérification des concepts ici encore

đŸ› ïž Pratique

Travaillez dans le répertoire GitHub partagé par votre enseignant pour la pratique et les exercices

  1. Créez une copie de ExceptionExample.java et le tester.
  2. Ajoutez une mĂ©thode double getDouble(String prompt) qui fonctionne de la mĂȘme maniĂšre que getInt, mais pour les nombres Ă  virgule flottante et ajouter une utilisation de cette mĂ©thode dans main.
  3. Remplacez System.out.println("EntrĂ©e invalide"); dans les blocs catch avec e.printStackTrace(); pour voir le message d’erreur complet sans toutefois faire planter le programme. Notez le type d’exception qui est lancĂ©e (celui qui s’affiche en premier dans le message d’erreur).

  1. Exemple applicant les classes implicites et le main d’instance de JEP 463 (pleinement intĂ©grĂ© aux outils Java22+) ↩ ↩2

© 2022-2025 David Crowley