Introduction
Dans ce laboratoire (lab), vous apprendrez à gérer efficacement les valeurs null lors de l'utilisation de collections en Java. Les collections sont des structures de données fondamentales, et il est essentiel d'écrire un code robuste capable de gérer en toute sécurité les situations où une variable de collection peut être null. Vous allez explorer comment tester si une collection est null, combiner les vérifications de nullité et de vacuité pour une validation complète, et utiliser la classe Optional pour améliorer la sécurité vis-à-vis des valeurs null, vous aidant ainsi à éviter les erreurs courantes de NullPointerException.
Tester si une collection est null
Dans cette étape, nous allons explorer comment gérer les valeurs null lors de l'utilisation de collections en Java. Les collections, comme List ou Set, sont des structures de données fondamentales, et il est essentiel d'écrire un code capable de gérer en toute sécurité les situations où une variable de collection peut être null.
Une valeur null en Java signifie qu'une variable ne fait référence à aucun objet. Si vous essayez d'accéder aux méthodes ou propriétés d'un objet null, votre programme plantera avec une NullPointerException. C'est une erreur très courante en Java, et apprendre à l'éviter est essentiel.
Commençons par créer un simple programme Java qui illustre le problème.
Ouvrez le fichier
HelloJava.javadans l'éditeur WebIDE s'il n'est pas déjà ouvert.Remplacez tout le contenu du fichier par le code suivant :
import java.util.List; public class HelloJava { public static void main(String[] args) { List<String> names = null; // Intentionnellement défini sur null // Cette ligne causera une NullPointerException si names est null // int size = names.size(); // System.out.println("Size of the list: " + size); System.out.println("Program finished."); } }Dans ce code, nous déclarons une
Listde chaînes de caractères appeléenameset la définissons explicitement surnull. Les lignes commentées montrent ce qui se passerait si nous essayions d'appeler la méthodesize()sur une listenull– cela entraînerait uneNullPointerException.Enregistrez le fichier (Ctrl+S ou Cmd+S).
Maintenant, compilons le programme. Ouvrez le Terminal en bas de l'éditeur WebIDE et assurez-vous que vous êtes dans le répertoire
~/project. Exécutez la commande suivante :javac HelloJava.javaVous ne devriez voir aucun message de sortie si la compilation réussit.
Maintenant, exécutez le programme :
java HelloJavaVous devriez voir la sortie suivante :
Program finished.Étant donné que la ligne qui causerait la
NullPointerExceptionest commentée, le programme s'exécute sans planter.
Maintenant, modifions le code pour vérifier la nullité avant d'essayer d'utiliser la collection.
Ouvrez à nouveau
HelloJava.javadans l'éditeur.Modifiez la méthode
mainpour inclure une vérification de nullité :import java.util.List; public class HelloJava { public static void main(String[] args) { List<String> names = null; // Intentionnellement défini sur null if (names != null) { // Ce code ne s'exécutera que si names n'est PAS null int size = names.size(); System.out.println("Size of the list: " + size); } else { System.out.println("The list is null."); } System.out.println("Program finished."); } }Nous avons ajouté une instruction
ifqui vérifie sinamesn'est pas égal ànull(names != null). Le code pour obtenir la taille et l'afficher se trouve maintenant à l'intérieur de ce blocif, ce qui signifie qu'il ne s'exécutera que sinamesest un objet de liste valide. Le blocelsegère le cas oùnamesestnull.Enregistrez le fichier.
Compilez le programme modifié :
javac HelloJava.javaExécutez le programme à nouveau :
java HelloJavaCette fois, vous devriez voir la sortie suivante :
The list is null. Program finished.Le programme a correctement identifié que la liste était
nullet a affiché le message approprié, évitant ainsi laNullPointerException.
Ce simple test if (collection != null) est le moyen le plus basique de prévenir les NullPointerException lors de la manipulation de collections. C'est une technique fondamentale que vous utiliserez fréquemment en programmation Java.
Combiner les vérifications de nullité et de vacuité
Dans l'étape précédente, nous avons appris à vérifier si une collection est null. Cependant, une collection peut également être vide (ne contenir aucun élément) même si elle n'est pas null. Dans de nombreux cas, vous pourriez vouloir traiter de manière similaire une collection null et une collection vide, ou du moins gérer les deux possibilités.
Pour vérifier si une collection est vide, on utilise la méthode isEmpty(). Cette méthode renvoie true si la collection ne contient aucun élément et false dans le cas contraire.
Modifions notre programme pour démontrer la différence entre une liste null et une liste vide, puis combinons les vérifications.
Ouvrez le fichier
HelloJava.javadans l'éditeur WebIDE.Remplacez le contenu par le code suivant :
import java.util.List; import java.util.ArrayList; // Import ArrayList public class HelloJava { public static void main(String[] args) { List<String> nullList = null; // Intentionnellement défini sur null List<String> emptyList = new ArrayList<>(); // Une liste vide System.out.println("Checking nullList:"); if (nullList != null) { System.out.println("nullList is not null."); if (nullList.isEmpty()) { System.out.println("nullList is empty."); } else { System.out.println("nullList is not empty."); } } else { System.out.println("nullList is null."); } System.out.println("\nChecking emptyList:"); if (emptyList != null) { System.out.println("emptyList is not null."); if (emptyList.isEmpty()) { System.out.println("emptyList is empty."); } else { System.out.println("emptyList is not empty."); } } else { System.out.println("emptyList is null."); } System.out.println("\nProgram finished."); } }Nous avons ajouté une
emptyListqui est initialisée comme une nouvelleArrayListvide. Nous effectuons ensuite les mêmes vérifications de nullité et de vacuité surnullListetemptyListpour voir la différence dans la sortie.Enregistrez le fichier.
Compilez le programme dans le Terminal :
javac HelloJava.javaExécutez le programme :
java HelloJavaVous devriez voir une sortie similaire à celle-ci :
Checking nullList: nullList is null. Checking emptyList: emptyList is not null. emptyList is empty. Program finished.Cette sortie montre clairement que
nullListestnull, tandis queemptyListn'est pasnullmais est vide.
Maintenant, combinons les vérifications de nullité et de vacuité en une seule condition. Un modèle courant consiste à vérifier si une collection est soit null soit vide.
Ouvrez
HelloJava.javadans l'éditeur.Modifiez la méthode
mainpour combiner les vérifications :import java.util.List; import java.util.ArrayList; public class HelloJava { public static void main(String[] args) { List<String> names = null; // Peut être null ou une liste vide // Vérification combinée : names est-il null OU names est-il vide ? if (names == null || names.isEmpty()) { System.out.println("The list is null or empty."); } else { System.out.println("The list is not null and not empty."); // Vous pouvez itérer ou accéder aux éléments en toute sécurité ici // Par exemple : // System.out.println("First element: " + names.get(0)); } // Testons avec une liste vide List<String> anotherList = new ArrayList<>(); System.out.println("\nChecking anotherList (empty):"); if (anotherList == null || anotherList.isEmpty()) { System.out.println("anotherList is null or empty."); } else { System.out.println("anotherList is not null and not empty."); } // Testons avec une liste non vide List<String> populatedList = new ArrayList<>(); populatedList.add("Item 1"); System.out.println("\nChecking populatedList (not empty):"); if (populatedList == null || populatedList.isEmpty()) { System.out.println("populatedList is null or empty."); } else { System.out.println("populatedList is not null and not empty."); } System.out.println("\nProgram finished."); } }Nous utilisons l'opérateur logique OU (
||) pour combiner les conditionsnames == nulletnames.isEmpty(). Le blocifs'exécutera si l'une des conditions est vraie. Nous avons également ajouté des tests avec une liste vide et une liste remplie pour voir comment se comporte la vérification combinée.Remarque importante : L'ordre des conditions dans
names == null || names.isEmpty()est crucial. Sinamesestnull, la première partie de la condition (names == null) est vraie. En raison de l'évaluation paresseuse (short - circuit evaluation) en Java, la deuxième partie (names.isEmpty()) n'est pas évaluée, évitant ainsi uneNullPointerException. Si vous écrivieznames.isEmpty() || names == nullet quenamesétaitnull, l'appel ànames.isEmpty()causerait uneNullPointerException. Vérifiez toujours la nullité en premier lorsque vous combinez avec d'autres vérifications sur l'objet.Enregistrez le fichier.
Compilez le programme :
javac HelloJava.javaExécutez le programme :
java HelloJavaVous devriez voir une sortie similaire à celle-ci :
The list is null or empty. Checking anotherList (empty): anotherList is null or empty. Checking populatedList (not empty): populatedList is not null and not empty. Program finished.Cela démontre comment la vérification combinée identifie correctement les listes
nullet vides, et les distingue des listes non vides. Cette vérification combinée est un moyen très courant et sûr de gérer les collections qui peuvent êtrenullou vides.
Utiliser Optional pour la sécurité contre les valeurs null
Dans cette étape, nous allons explorer une approche plus moderne pour gérer les valeurs null potentielles en Java en utilisant la classe Optional, introduite en Java 8. Optional est un objet conteneur qui peut ou non contenir une valeur non nulle. Il offre un moyen de représenter de manière plus explicite la présence ou l'absence d'une valeur, ce qui peut aider à réduire le risque de NullPointerException.
Bien que les vérifications if (collection != null) soient parfaitement valides et nécessaires dans de nombreuses situations, Optional peut rendre votre code plus lisible et expressif, en particulier lorsqu'il s'agit de méthodes qui peuvent retourner une valeur ou null.
Voyons comment nous pouvons utiliser Optional avec une collection. Bien que Optional soit généralement utilisé pour des valeurs uniques, vous pourriez rencontrer des scénarios où une méthode retourne un Optional<List<SomeObject>>.
Ouvrez le fichier
HelloJava.javadans l'éditeur WebIDE.Remplacez le contenu par le code suivant qui montre comment utiliser
Optionalavec une liste potentiellement nulle :import java.util.List; import java.util.ArrayList; import java.util.Optional; // Import Optional public class HelloJava { // Une méthode qui peut retourner un Optional contenant une liste, ou un Optional vide public static Optional<List<String>> getNames(boolean includeNames) { if (includeNames) { List<String> names = new ArrayList<>(); names.add("Alice"); names.add("Bob"); return Optional.of(names); // Retourne un Optional contenant la liste } else { return Optional.empty(); // Retourne un Optional vide } } public static void main(String[] args) { // Cas 1 : Obtenir les noms lorsque includeNames est true Optional<List<String>> namesOptional1 = getNames(true); System.out.println("Checking namesOptional1:"); // Vérifie si l'Optional contient une valeur if (namesOptional1.isPresent()) { List<String> names = namesOptional1.get(); // Récupère la liste de l'Optional System.out.println("List is present. Size: " + names.size()); // Vous pouvez également vérifier si la liste elle - même est vide if (names.isEmpty()) { System.out.println("List is empty."); } else { System.out.println("List is not empty. First name: " + names.get(0)); } } else { System.out.println("List is not present (Optional is empty)."); } System.out.println("---"); // Cas 2 : Obtenir les noms lorsque includeNames est false Optional<List<String>> namesOptional2 = getNames(false); System.out.println("Checking namesOptional2:"); if (namesOptional2.isPresent()) { List<String> names = namesOptional2.get(); System.out.println("List is present. Size: " + names.size()); if (names.isEmpty()) { System.out.println("List is empty."); } else { System.out.println("List is not empty. First name: " + names.get(0)); } } else { System.out.println("List is not present (Optional is empty)."); } System.out.println("\nProgram finished."); } }Dans ce code :
- Nous définissons une méthode
getNamesqui retourne unOptional<List<String>>. Cette méthode simule un scénario où vous pouvez obtenir une liste ou rien du tout (représenté par unOptionalvide). - Dans la méthode
main, nous appelonsgetNamesavectrueetfalsepour tester les deux cas. - Nous utilisons
namesOptional.isPresent()pour vérifier si l'Optionalcontient une liste. - Si
isPresent()est vrai, nous utilisonsnamesOptional.get()pour récupérer la liste. Cela est sûr car nous avons déjà vérifié la présence. - À l'intérieur du bloc
isPresent(), nous pouvons ensuite effectuer des vérifications sur la liste elle - même, commenames.isEmpty().
- Nous définissons une méthode
Enregistrez le fichier.
Compilez le programme dans le Terminal :
javac HelloJava.javaExécutez le programme :
java HelloJavaVous devriez voir une sortie similaire à celle - ci :
Checking namesOptional1: List is present. Size: 2 List is not empty. First name: Alice --- Checking namesOptional2: List is not present (Optional is empty). Program finished.Cette sortie montre comment
Optionalnous aide à gérer le cas où une liste peut ne pas être retournée du tout.
Optional offre également d'autres méthodes utiles pour gérer l'absence d'une valeur, telles que :
orElse(defaultValue): Retourne la valeur si elle est présente, sinon retourne une valeur par défaut.orElseGet(supplier): Retourne la valeur si elle est présente, sinon retourne le résultat de la fonctionsupplier.orElseThrow(exceptionSupplier): Retourne la valeur si elle est présente, sinon lance une exception produite parexceptionSupplier.ifPresent(consumer): Effectue l'action donnée si une valeur est présente.
Modifions le code pour utiliser ifPresent d'une manière plus concise pour gérer la liste lorsqu'elle est présente.
Ouvrez
HelloJava.javadans l'éditeur.Modifiez la méthode
mainpour utiliserifPresent:import java.util.List; import java.util.ArrayList; import java.util.Optional; public class HelloJava { public static Optional<List<String>> getNames(boolean includeNames) { if (includeNames) { List<String> names = new ArrayList<>(); names.add("Alice"); names.add("Bob"); return Optional.of(names); } else { return Optional.empty(); } } public static void main(String[] args) { // Cas 1 : Obtenir les noms lorsque includeNames est true Optional<List<String>> namesOptional1 = getNames(true); System.out.println("Checking namesOptional1 using ifPresent:"); namesOptional1.ifPresent(names -> { // Ce bloc ne s'exécute que si namesOptional1 contient une liste System.out.println("List is present. Size: " + names.size()); if (names.isEmpty()) { System.out.println("List is empty."); } else { System.out.println("List is not empty. First name: " + names.get(0)); } }); if (!namesOptional1.isPresent()) { // Il faut toujours une vérification si vous devez gérer le cas d'absence System.out.println("List is not present (Optional is empty)."); } System.out.println("---"); // Cas 2 : Obtenir les noms lorsque includeNames est false Optional<List<String>> namesOptional2 = getNames(false); System.out.println("Checking namesOptional2 using ifPresent:"); namesOptional2.ifPresent(names -> { System.out.println("List is present. Size: " + names.size()); if (names.isEmpty()) { System.out.println("List is empty."); } else { System.out.println("List is not empty. First name: " + names.get(0)); } }); if (!namesOptional2.isPresent()) { System.out.println("List is not present (Optional is empty)."); } System.out.println("\nProgram finished."); } }Nous avons remplacé la structure
if (namesOptional.isPresent()) { ... namesOptional.get() ... }parnamesOptional.ifPresent(names -> { ... }). Le code à l'intérieur de l'expression lambda (names -> { ... }) ne s'exécutera que si l'Optionalcontient une valeur. Nous avons toujours ajouté une vérificationif (!namesOptional.isPresent())pour gérer le cas où l'Optionalest vide, carifPresentne gère que le cas de présence.Enregistrez le fichier.
Compilez le programme :
javac HelloJava.javaExécutez le programme :
java HelloJavaLa sortie devrait être la même que précédemment, démontrant que
ifPresentoffre une autre façon de gérer la présence d'une valeur dans unOptional.
L'utilisation de Optional peut rendre l'intention de votre code plus claire en ce qui concerne la possibilité d'absence d'une valeur, et elle vous encourage à gérer explicitement cette absence, réduisant ainsi la probabilité de NullPointerException inattendues.
Résumé
Dans ce laboratoire (lab), nous avons appris à gérer les collections null en Java pour éviter les NullPointerException. Nous avons commencé par démontrer le problème lié à l'appel de méthodes sur une collection null, qui entraîne une erreur à l'exécution.
Ensuite, nous avons exploré différentes techniques pour vérifier en toute sécurité si une collection est null avant d'essayer d'accéder à ses éléments ou à ses propriétés. Il s'agit d'une compétence fondamentale pour écrire un code Java robuste et exempt d'erreurs.



