Défi

Dans cet exercice, nous allons concevoir un programme Java robuste qui couvre tous les aspects de la conception du code de gestion des exceptions.

Imaginons un programme mettant en œuvre les fonctionnalités de base des distributeurs automatiques de billets dans la région de Montpellier.

Une des règles fondamentales que le programme doit implémenter est que l'on ne puisse pas retirer de l'argent dont le montant dépasse le solde bancaire du compte courant.

On a proposé un code qui fait ce qui lui est demandé et ne fait rien lorsque lorsque l'on veut retirer un montant supérieur à celui du compte courant.

Le Team Manager a donc décidé de vous confier la responsabilité de corriger les erreurs du programme car il sait que vous avez suivi notre cours d'exceptions.

Votre défi est donc de corriger le programme suivant et également d'utiliser les bonnes pratiques du mécanisme de gestion des exceptions proposé par Java afin que le programme puisse fonctionner à nouveau et implémenter correctement la règle sur les retraits.

Question

Vous trouverez ci-dessous le programme Java contenant une classe représentant un compte bancaire lambda dans lequel les utilisateurs peuvent afficher, déposer ou retirer de l'argent.

Le code ci-dessous est utilisé pour enregistrer les transactions et ne fait rien lorsqu'un utilisateur essaie de retirer un montant supérieur à celui qu’il a dans son compte.

Nous avons donc trois problèmes :

  1. Comment gérer les exceptions

  2. Comment utiliser le mécanisme d'exceptions pour implémenter le signalement à l'utilisateur qu'il ne doit retirer qu'un montant inférieur à celui qu'il a sur son compte.

  3. Gérer les ressources utilisées correctement et capturer les exceptions qu'on va lever afin que le programme puisse fonctionner correctement.

1
import java.util.Scanner;
2
3
public class Compte {
4
    private int solde = 100;
5
6
    public static void main(String[] args) throws InterruptedException {
7
        Compte compte = new Compte();
8
        System.out.println("""
9
                Bonjour et Bienvenue dans notre banque
10
                \tTapez 1 ==> Vérifiez le solde de votre compte
11
                \tTapez 2 ==> Faire un dépôt
12
                \tTapez 3 ==> Faire un retrait
13
                \tTapez 4 pour enregistrer les opérations effectuées et quitter l'application """);
14
        Scanner sc = new Scanner(System.in);
15
        boolean isWrongAnswer = true;
16
        while (isWrongAnswer) {
17
            System.out.println("*********************************************************************************");
18
            System.out.println("Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:");
19
            switch (sc.nextInt()) {
20
                case 1 -> compte.soldeActuel();
21
                case 2 -> {
22
                    System.out.println("Entrez le montant du dépôt");
23
                    compte.depot(sc.nextInt());
24
                }
25
                case 3 -> {
26
                    System.out.println("Entrez le montant du retrait");
27
                    compte.retrait(sc.nextInt());
28
                }
29
                case 4 -> {
30
                    System.out.println("Opération(s) enregistrée(s)! Au revoir");
31
                    Thread.sleep(2000);
32
                    isWrongAnswer = false;
33
                }
34
                default -> {
35
                    System.out.println("Tapez uniquement les nombres entre 1 et 4");
36
                }
37
            }
38
        }
39
    }
40
41
    /* Le solde doit toujours être positif */
42
    public int getSolde() {
43
        return solde;
44
    }
45
46
    /* Le montant à retirer doit toujours être > le solde actuel */
47
    public void retrait(int montant) {
48
        this.solde -= montant;
49
        soldeActuel();
50
    }
51
52
    public void depot(int montant) {
53
        this.solde += montant;
54
        soldeActuel();
55
    }
56
57
    public void soldeActuel() {
58
        System.out.println("Le solde du compte courant est de " + this.getSolde() + " euros");
59
    }
60
    
61
}
1
C:\>javac Compte.java
2
java: unreported exception java.lang.InterruptedException; must be caught or declared to be thrown

Nous devons donc traiter tous les problèmes liés à ce programme en utilisant le mécanisme de gestion des exceptions Java que nous avons appris dans le cours.

Indice

1. Le compilateur affiche une exception de type InterruptedException.

La plupart des classes et méthodes intégrées au langage Java sont codées de façon à gérer les exceptions qu'elles peuvent générer. Et leurs exceptions sont dites vérifiées.

Nous allons donc ici soit gérer l'exception InterruptedException générée par la méthode sleep( ) de la classe Thread (classe intégrée du langage Java), soit la propager (la spécifier).

1
public static void main(String[] args) throws InterruptedException { ... }

Nous avons donc ajouté la spécification de l'exception InterruptedException dans la déclaration de la méthode main( ) à l'aide du mot-clé throws afin de la propager et de déléguer son traitement à une méthode située plus haut dans la liste des appels de méthode.

1
C:\>javac Compte.java
2
Bonjour et Bienvenue dans notre banque
3
	Tapez 1 ==> Vérifiez le solde de votre compte
4
	Tapez 2 ==> Faire un dépôt
5
	Tapez 3 ==> Faire un retrait
6
	Tapez 4 pour enregistrer les opérations effectuées et quitter l'application
7
*********************************************************************************
8
	Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:
9
1
10
Le solde du compte courant est de 100 euros
11
*********************************************************************************
12
	Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:
13
3
14
Entrez le montant du retrait
15
250
16
Le solde du compte courant est de -150 euros
17
*********************************************************************************
18
	Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:
19
4
20
Opération(s) enregistrée(s)! Au revoir
21
22
Process finished with exit code 0

Le code compile, cependant, on voit bien que l’on a effectué un retrait de 250 euros sur un compte au solde de 100 euros. Après cette opération, le solde affiche -150 euros

Pour corriger cela, il ne reste plus qu'à mettre en place la gestion de la règle sur les retraits d'argent.

Indice

2. L’implémentation de cette règle peut se faire par un mécanisme de gestion d’exception personnalisée.

Nous allons créer une exception personnalisée appelée MontantSoldeDoitEtreSuperieurAuMontantRetraitException.

1
class MontantSoldeDoitEtreSuperieurAuMontantRetraitException extends Exception {
2
    private String message;
3
4
    public MontantSoldeDoitEtreSuperieurAuMontantRetraitException(String message) {
5
        this.message = message;
6
    }
7
8
    public String getMessage() {
9
        return this.message;
10
    }
11
}

Nous allons donc l'appliquer dans notre fonction de retrait de la classe compte comme suit :

1
    /* Le montant à retirer doit toujours être > au solde actuel */
2
    public void retrait(int montant) {
3
        if (montant > solde) {
4
            throw new MontantSoldeDoitEtreSuperieurAuMontantRetraitException (
5
                    "Le solde actuel de " + compte.getSolde( ) + " euros est inférieur par rapport au montant de " + montant + " euros que vous souhaitez retirer");
6
        }
7
        this.solde -= montant;
8
        soldeActuel();
9
    }

En effet, nous levons notre exception à l'aide du mot-clé throw. Ainsi à l'aide de ce code, nous générerons une exception permettant au programme de gérer les retraits supérieurs au solde courant.

Ensuite on spécifie l'exception ainsi levée partout où la méthode (la méthode retrait( )) qui la lève est appelée.

1
public void retrait(int montant) throws MontantSoldeDoitEtreSuperieurAuMontantRetraitException { ... }
1
public static void main(String[] args) throws InterruptedException, MontantSoldeDoitEtreSuperieurAuMontantRetraitException { ... }
1
C:\>javac Compte.java
2
Bonjour et Bienvenue dans notre banque
3
	Tapez 1 ==> Vérifiez le solde de votre compte
4
	Tapez 2 ==> Faire un dépôt
5
	Tapez 3 ==> Faire un retrait
6
	Tapez 4 pour enregistrer les opérations effectuées et quitter l'application
7
Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:
8
3
9
Entrez le montant du retrait
10
400
11
Exception in thread "main" exceptions.MontantSoldeDoitEtreSuperieurAuMontantRetraitException 
12
	at exceptions.Compte.retrait(Compte.java:50)
13
	at exceptions.Compte.main(Compte.java:28)
14
15
Process finished with exit code 1

On voit maintenant que lorsqu'un utilisateur tente de retirer 400 euros alors que son solde est de 100 euros, le compilateur Java affiche notre exception qui défend cette opération.

Nous allons maintenant gérer notre exception à l'aide du mécanisme de capture et de gestion des exception des exceptions en Java, le try-catch-finally.

Indice

3. Capture et gestion des exceptions

  • Ce code utilise la ressource scanner sans pour autant la libérer à la fin de nos opérations.

  • Ensuite on peut directement capter et afficher le message de l'exception personnalisée écrite ci-dessus dans la main( ) de l'application.

Procédons d'abord par la capture de notre exception personnalisée de type MontantSoldeDoitEtreSuperieurAuMontantRetraitException et libérer la ressource scanner qu'on utilise.

1
        ...
2
				Scanner sc = new Scanner(System.in);
3
        try {
4
            ...
5
        } catch (MontantSoldeDoitEtreSuperieurAuMontantRetraitException exception) {
6
            System.out.println(exception.getMessage());
7
        } finally {
8
            sc.close();
9
        }
10
    }

On remarque ici qu'on a enlevé la spécification de l'exception MontantSoldeDoitEtreSuperieurAuMontantRetraitException dans la déclaration de la méthode main( ) puisque maintenant on a capté et géré l'exception en question à l'aide du mécanisme du try-catch-finally.

On a aussi libéré la ressource du scanner dans le bloc de code finally.

Indice

Pour finir, nous allons remplacer le mécanisme du try...catch...finally par celui du try-with-resources pour rendre le code plus succinct.

1
 try (Scanner sc = new Scanner(System.in)) { ... }

Solution

Le résultat final

Voici donc notre programme ainsi rendu robuste et comprenant les bonnes règles de gestion des exceptions.

1
import java.util.Scanner;
2
3
public class Compte {
4
    private int solde = 100;
5
6
    public static void main(String[] args) throws InterruptedException {
7
        Compte compte = new Compte();
8
        System.out.println("""
9
                Bonjour et Bienvenue dans notre banque
10
                \tTapez 1 ==> Vérifiez le solde de votre compte
11
                \tTapez 2 ==> Faire un dépôt
12
                \tTapez 3 ==> Faire un retrait
13
                \tTapez 4 pour enregistrer les opérations effectuées et quitter l'application """);
14
        try (Scanner sc = new Scanner(System.in)) {
15
16
            boolean isWrongAnswer = true;
17
            while (isWrongAnswer) {
18
                System.out.println("*********************************************************************************");
19
                System.out.println("\tVeuillez saisir le numéro de la transaction que vous souhaitez effectuer:");
20
                switch (sc.nextInt()) {
21
                    case 1 -> compte.soldeActuel();
22
                    case 2 -> {
23
                        System.out.println("Entrez le montant du dépôt");
24
                        compte.depot(sc.nextInt());
25
                    }
26
                    case 3 -> {
27
                        System.out.println("Entrez le montant du retrait");
28
                        compte.retrait(sc.nextInt());
29
                    }
30
                    case 4 -> {
31
                        System.out.println("Opération(s) enregistrée(s)! Au revoir");
32
                        Thread.sleep(2000);
33
                        isWrongAnswer = false;
34
                    }
35
                    default -> System.out.println("Tapez uniquement les nombres entre 1 et 4");
36
                }
37
            }
38
        } catch (MontantSoldeDoitEtreSuperieurAuMontantRetraitException exception) {
39
            System.out.println(exception.getMessage());
40
        }
41
    }
42
43
    /* Le solde doit toujours être positif */
44
    public int getSolde() {
45
        return solde;
46
    }
47
48
    /* Le montant à retirer doit toujours être > le solde actuel */
49
    public void retrait(int montant) throws MontantSoldeDoitEtreSuperieurAuMontantRetraitException {
50
        if (montant > solde) {
51
            throw new MontantSoldeDoitEtreSuperieurAuMontantRetraitException (
52
                    "Le solde actuel de " + this.getSolde() + " euros est inférieur par rapport au montant de " +
53
                            montant + " euros que vous souhaitez retirer");
54
        }
55
        this.solde -= montant;
56
        soldeActuel();
57
    }
58
59
    public void depot(int montant) {
60
        this.solde += montant;
61
        soldeActuel();
62
    }
63
64
    public void soldeActuel() {
65
        System.out.println("Le solde du compte courant est de " + this.getSolde() + " euros");
66
    }
67
68
}
69
70
class MontantSoldeDoitEtreSuperieurAuMontantRetraitException extends Exception {
71
    private final String message;
72
73
    public MontantSoldeDoitEtreSuperieurAuMontantRetraitException(String message) {
74
        this.message = message;
75
    }
76
77
    public String getMessage() {
78
        return this.message;
79
    }
80
}
1
C:\>javac Compte.java
2
Bonjour et Bienvenue dans notre banque
3
	Tapez 1 ==> Vérifiez le solde de votre compte
4
	Tapez 2 ==> Faire un dépôt
5
	Tapez 3 ==> Faire un retrait
6
	Tapez 4 pour enregistrer les opérations effectuées et quitter l'application
7
*********************************************************************************
8
	Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:
9
1
10
Le solde du compte courant est de 100 euros
11
*********************************************************************************
12
	Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:
13
2
14
Entrez le montant du dépôt
15
150
16
Le solde du compte courant est de 250 euros
17
*********************************************************************************
18
	Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:
19
3
20
Entrez le montant du retrait
21
200
22
Le solde du compte courant est de 50 euros
23
*********************************************************************************
24
	Veuillez saisir le numéro de la transaction que vous souhaitez effectuer:
25
3
26
Entrez le montant du retrait
27
100
28
Le solde actuel de 50 euros est moindre par rapport au montant de 100 euros que vous voulez retirer
29
30
Process finished with exit code 0