CodeGym /Cours /JAVA 25 SELF /finally et throw : finalisation et génération d'exception...

finally et throw : finalisation et génération d'exceptions

JAVA 25 SELF
Niveau 11, Leçon 3
Disponible

1. Découverte du bloc finally

Lorsque vous travaillez avec des ressources — fichiers, connexions réseau, bases de données — il est important d’être certain qu’elles seront fermées ou libérées toujours, même si une erreur survient pendant l’exécution. En Java, il existe pour cela un bloc spécial — finally.

Comment fonctionne finally ?

Le bloc finally fait partie de la construction try-catch-finally. Le code à l’intérieur de finally s’exécute toujours (s’il est présent) — qu’il y ait eu une exception ou non. Même s’il y a un return dans try ou qu’une exception est levée, finally s’exécutera quand même (sauf si l’ordinateur est éteint ou si le programme est terminé de force via System.exit(0)).

Syntaxe :

try {
    // Code susceptible de lever une exception
} catch (ExceptionType e) {
    // Traitement de l'erreur
} finally {
    // Ce code s'exécutera toujours !
}

Exemple

try {
    System.out.println("Début de l'exécution");
    int result = 10 / 0; // une erreur va se produire ici
    System.out.println("Résultat: " + result);
} catch (ArithmeticException e) {
    System.out.println("Erreur: division par zéro");
} finally {
    System.out.println("Ce code s'exécutera dans tous les cas");
}

Résultat de l’exécution :

Début de l'exécution
Erreur: division par zéro
Ce code s'exécutera dans tous les cas

Que se passe-t-il ?

  1. Dans try, nous tentons de diviser deux nombres et obtenons une erreur.
  2. Si une erreur survient lors de la division — catch la traite.
  3. Mais ! Quoi qu’il arrive, finally s’exécute et écrit un message dans la console.

2. finally sans catch

Il peut y avoir 3 variantes de la construction :

  • Complète : try-catch-finally
  • Sans finally : try-catch
  • Sans catch : try-finally

La troisième variante est utilisée quand la capture et le traitement de l’erreur seront effectués par une méthode de niveau supérieur. Mais le bloc finally est nécessaire pour garantir l’exécution d’un certain code :

  • Fermeture de fichiers, connexions réseau, bases de données.
  • Libération de toute ressource (par exemple, des verrous).
  • Journalisation : consigner des informations sur la fin de l’opération.

Exemple :

try {
    System.out.println("On divise des nombres");
    int result = 10 / 0;   // erreur !
    System.out.println("Résultat: " + result);
} finally {
    System.out.println("Le bloc finally a été exécuté");
}

Résultat :

On divise des nombres
Le bloc finally a été exécuté
Exception in thread "main" java.lang.ArithmeticException: / by zero

Quand finally NE s’exécute-t-il pas ?

Il s’exécute presque toujours. Exceptions — si :

  1. Le programme a été terminé de force via : System.exit(0).
  2. Le thread dans lequel s’exécute finally a été « tué » de force.
  3. L’ordinateur a été éteint.

3. L’opérateur throw : comment générer une exception soi-même

Parfois, Java « lève » elle-même des exceptions (par exemple, division par zéro, dépassement des limites d’un tableau). Mais il existe des situations où vous souhaitez signaler explicitement : « C’est une erreur ! Je ne peux pas continuer l’exécution ! ». Pour cela, Java fournit l’opérateur throw.

Analogie : Si vous êtes dans un magasin et voyez un produit périmé — vous déposez une réclamation. De même dans le code : si quelque chose ne va pas — vous levez une exception.

Syntaxe de throw

throw new ExceptionType("Message d'erreur");

ExceptionType — toute classe dérivant de Throwable (généralement Exception ou RuntimeException). Entre parenthèses, un message qui aide à comprendre ce qui s’est mal passé.

Exemple : validation des arguments d’une méthode

public static int safeDivide(int a, int b) {
    if (b == 0) {
        throw new IllegalArgumentException("Le diviseur ne peut pas être égal à zéro");
    }
    return a / b;
}

Utilisation :

public static void main(String[] args) {
    try {
        int result = safeDivide(10, 0);
        System.out.println("Résultat: " + result);
    } catch (IllegalArgumentException e) {
        System.out.println("Erreur: " + e.getMessage());
    }
}

Résultat :

Erreur: Le diviseur ne peut pas être égal à zéro

Quand utiliser throw ?

  • Validation des arguments d’une méthode (par exemple, si null est passé ou si les données sont incorrectes).
  • Vérification de l’état d’un objet (par exemple, tentative de retirer de l’argent d’un compte qui contient 0 €).
  • À l’intérieur de catch — si vous souhaitez « relancer » l’exception plus loin (par exemple, pour ajouter des informations supplémentaires).

4. Combiner try-catch-finally et throw

Parfois, ces constructions fonctionnent ensemble. Par exemple, vous interceptez une erreur, puis décidez d’en lever une autre, plus informative.

public static int parseAndDivide(String text, int divisor) {
    try {
        int number = Integer.parseInt(text);
        if (divisor == 0) {
            throw new IllegalArgumentException("Le diviseur ne peut pas être égal à zéro");
        }
        return number / divisor;
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("La chaîne '" + text + "' n'est pas un nombre");
    } finally {
        System.out.println("Tentative de traiter la chaîne: " + text);
    }
}

Utilisation :

try {
    int result = parseAndDivide("42a", 2);
    System.out.println("Résultat: " + result);
} catch (IllegalArgumentException e) {
    System.out.println("Erreur: " + e.getMessage());
}

Résultat :

Tentative de traiter la chaîne: 42a
Erreur: La chaîne '42a' n'est pas un nombre

Nuance importante : return et finally

Même s’il y a un return dans le bloc try, finally s’exécutera quand même !

public static int getValue() {
    try {
        return 10;
    } finally {
        System.out.println("finally s'exécutera quand même !");
    }
}

L’appel à getValue() affichera :

finally s'exécutera quand même !

5. Erreurs courantes lors de l’utilisation de finally et throw

Erreur n° 1 : oublier de fermer une ressource sans finally.
Problème très fréquent : on ouvre un fichier, on ne le referme pas — fuite de ressources. Utilisez toujours finally (ou try-with-resources, dont nous parlerons plus tard).

Erreur n° 2 : lever une exception sans la traiter.
Si vous levez une exception avec throw mais que vous ne la capturez nulle part (pas de try-catch), le programme s’arrêtera brutalement. Réfléchissez toujours à qui va capturer votre exception.

Erreur n° 3 : return dans finally.
Si vous avez écrit par erreur un return à l’intérieur de finally, il « éclipsera » tous les return ou throw précédents. Cela peut entraîner des bogues très difficiles à détecter. C’est fortement déconseillé !

public int tricky() {
    try {
        return 1;
    } finally {
        return 2; // DANGEREUX: 2 sera renvoyé, pas 1 !
    }
}

Résultat : 2 sera renvoyé, alors que dans try il y avait 1.

Erreur n° 4 : perte d’information sur l’exception.
Si vous capturez une exception, puis en levez une nouvelle sans conserver les informations sur l’ancienne (e), vous perdez la pile d’appels, ce qui complique le débogage. Il vaut mieux écrire :

catch (NumberFormatException e) {
    throw new IllegalArgumentException("Erreur de conversion", e);
}
1
Mission
JAVA 25 SELF, niveau 11, leçon 3
Bloqué
Robot aspirateur et son rapport d'achèvement 🧹
Robot aspirateur et son rapport d'achèvement 🧹
1
Mission
JAVA 25 SELF, niveau 11, leçon 3
Bloqué
Système de score : uniquement des valeurs positives ! 🏅
Système de score : uniquement des valeurs positives ! 🏅
1
Mission
JAVA 25 SELF, niveau 11, leçon 3
Bloqué
Module critique et terminaison d'urgence avec rapport 💥
Module critique et terminaison d'urgence avec rapport 💥
1
Mission
JAVA 25 SELF, niveau 11, leçon 3
Bloqué
Validation du nom d'utilisateur dans le système d'inscription 📝
Validation du nom d'utilisateur dans le système d'inscription 📝
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION