Erreur/Exception
Objectifs
Comprendre ce qu'est une erreur/exception en Java
Différencier les erreurs de logique métier, de compilation et d'exécution
Les approches de résolution des erreurs de logique métier et de compilation
Mise en situation
Lorsque nous lançons un programme, on peut rencontrer des problèmes, sous la forme de différents types d'erreurs et faire face à un comportement imprévisible ou un fonctionnement exceptionnel de notre programme.
Il existe deux types de familles d'erreurs qui se produisent souvent :
Les erreurs de code logiciel, ce qui inclut les erreurs de compilation et les erreurs d'exécution
Les erreurs de logique métier .
Erreur de code logiciel
Ce sont des erreurs liées au code et au fonctionnement de la JVM. Lorsqu'elles se produisent, la JVM arrête le programme et produit un message d'erreur. Java va donc lever une exception (relever une erreur) car nous sommes confrontés à un comportement exceptionnel de l'application (le plantage ou crash de l'application).
On distingue deux types d'erreurs:
Les erreurs de compilation : elles surviennent lors de la phase de compilation du code, c'est-à-dire la phase où la JVM va traduire (compiler) le fichier texte du code source .java en fichier binaire .class (bytecode/code machine ou fichier exécutable par la machine) grâce au compilateur javac.
Les erreurs d'exécution : elles surviennent lors de la phase d'exécution du fichier binaire .class par la JVM (Java Virtual Machine).
1. Les erreurs de compilation/Throwable, Error
Ces erreurs portent généralement sur les violations des règles syntaxiques et sémantiques de la grammaire du langage Java.
Exemple : Règles Syntaxiques
Une violation des règles grammaticales du langage peut être par exemple : le non-respect des règles de nomination de variables...
public class Main {
public static void main(String[] args) { System.out.println "hello World }
}
console@user:~$
java: '(' expected
java: ')' expected
java: unclosed string literal
java: ';' expected
Ce code viole quelques règles syntaxiques qui sont exposées dans la console telles que :
les parenthèses ouvrantes et fermantes manquantes à l'appel de la méthode println( ) pour l'affichage des données à la console
la non-fermeture de la chaîne de caractère par un
“
et enfin le point-virgule manquant
;
à la fin de l'instruction.
Exemple : Règles sémantiques
Une violation des règles sémantiques peut être par exemple : l'utilisation de mots interdits, de code non interprétable, de types incorrects...
public class Main {
public static void main(String[] args) {
...
String 123 = "123";
boolean zero = 0;
int entier = 2.5;
float nombre-a-virgule = 100;
System.out.println(~);
}
}
java: not a statement
java: incompatible types: int cannot be converted to boolean
java: possible lossy conversion from double to int
java: illegal start of expression
Ce code viole plusieurs règles sémantiques du langage Java telles que :
les noms de variables Java ne peuvent pas commencer par des nombres ou n'être simplement que des nombres
des conversions de types incorrects ou l'insertion de types incompatibles entre eux
des éléments qui ne sont pas gérés par le langage Java.
Fondamental : Correction des erreurs de compilation
Choisissez de bons éditeurs de code comme Atom, VS Code, Sublime Text... ou encore mieux, de bons IDE comme Eclipse, NetBeans ou Intellij Idea Ultimate qui peuvent détecter les erreurs de grammaire (syntaxe/sémantique) en mettant en évidence (coloration, surlignage...) des parties de code contenant des anomalies directement lors de l'écriture de votre code.
Cependant, ils ne sont pas toujours suffisants ou ne répondent pas toujours à toutes nos envies. Par conséquent, Java fournit un mécanisme de gestion des erreurs : la gestion des exceptions qu'on verra au chapitre suivant.
2. Les erreurs d'exécution/RuntimeError
Lorsque l'étape de compilation est terminée et que le programme produit un bytecode, on passe à la phase d'exécution de ce bytecode.
Pendant la phase d'exécution, le programme peut se terminer brusquement et donc détecter des erreurs d'exécution impossibles à détecter lors de la phase de compilation.
Exemple : Type d'erreur d'exécution
Ce genre d'erreur se produit lorsque le programme effectue une opération interdite ou illégale.
public class DiviserParZero {
public static void main(String[] args) {
int distance = 10;
int temps = 0;
System.out.println("La vitesse vaut ==> " + distance / temps);
}
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at DiviserParZero.main(DiviserParZero.java)
La JVM vient de relever une ArithmeticException qui expose l'exécution d'une opération illégale ou interdite : la division par zéro.
Nous savons bien que la vitesse est le rapport de la distance par le temps. La compilation de ce programme se passe sans problème.
Cependant, l'opération de division par zéro est illégale, donc cette erreur sera détectée à l'exécution de ce programme.
Fondamental : Correction des erreurs d'exécution
En testant notre code, et en utilisant des techniques de vérifications formelles (ex PathFinder), on arrive à bien s'assurer de ne pas rencontrer d'erreurs d'exécution.
On peut utiliser le système de débogage ou la gestion des exceptions pour traiter ce genre d'erreurs.
Erreur de logique métier
Ce sont des erreurs difficiles à détecter car elles ne provoquent pas d'interruption de programme mais produisent plutôt des résultats logiquement incohérents.
Exemple : Type d'erreur de logique métier classique
public class Main {
public static void main(String[] args) {
String[] nba = { "Lebron James", "Stephen Curry", "Kevin Durant"};
String[] uefa = { "Cristiano Ronaldo", "Lionel Messi", "Kylian Mbappé"};
/* Souhait : Afficher la liste des joueurs de la NBA */
for (String nba_players : uefa) {
System.out.println(nba_players);
}
}
}
console@user:~$
Cristiano Ronaldo
Lionel Messi
Kylian Mbappé
En effet, l'erreur illustrée ci-dessus sera difficile à détecter car l'application affiche bien ce qu'on lui demande et ne plante pas.
Cependant, Lionel Messi sur la liste des basketteurs NBA est logiquement incorrect (voire impossible).
Fondamental : Correction des erreurs de logique métier
Pour détecter et corriger les erreurs de logique métier, on a besoin des programmes appelés debugger qui vont suivre, instruction par instruction, l'exécution du programme et relever le contenu de toutes les variables à chaque étape.
Syntaxe : À retenir
Dans ce chapitre, les points importants à retenir sont :
Les erreurs de logique métier sont difficiles à détecter car elles passent souvent inaperçues puisque le programme compile et s'exécute sans signaler un quelconque problème ; on a vu comment les détecter et les corriger.
Les erreurs de code Java qui se produisent :
lors de la phase de compilation du programme : on a abordé différentes approches, techniques et mécanismes qu'offrent certains outils pour les détecter et les corriger tels que les bons éditeurs de code et les bons EDI, un débugger ou la gestion des exceptions.
lors de la phase d'exécution du programme : on a abordé différentes approches qu'offrent certains outils pour les détecter et les corriger tels que PathFinder et aussi le mécanisme Java pour la gestion des exceptions.
Complément :
Les règles de grammaire (spécifications) Java à respecter afin d'éviter les erreurs de compilation : https://docs.oracle.com/javase/specs/jls/se15/html/jls-2.html
Lien vers la documentation de PathFinder : http://javapathfinder.sourceforge.net/
Liens vers la documentation des techniques de débogage :