Comment vérifier si une collection est null en Java

JavaJavaBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

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.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/DataStructuresGroup(["Data Structures"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java/BasicSyntaxGroup -.-> java/if_else("If...Else") java/DataStructuresGroup -.-> java/collections_methods("Collections Methods") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/exceptions("Exceptions") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/arraylist("ArrayList") subgraph Lab Skills java/if_else -.-> lab-559942{{"Comment vérifier si une collection est null en Java"}} java/collections_methods -.-> lab-559942{{"Comment vérifier si une collection est null en Java"}} java/classes_objects -.-> lab-559942{{"Comment vérifier si une collection est null en Java"}} java/exceptions -.-> lab-559942{{"Comment vérifier si une collection est null en Java"}} java/arraylist -.-> lab-559942{{"Comment vérifier si une collection est null en Java"}} end

Tester une collection pour la nullité

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.

  1. Ouvrez le fichier HelloJava.java dans l'éditeur WebIDE s'il n'est pas déjà ouvert.

  2. 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 List de chaînes de caractères appelée names et la définissons explicitement sur null. Les lignes commentées montrent ce qui se passerait si nous essayions d'appeler la méthode size() sur une liste null – cela entraînerait une NullPointerException.

  3. Enregistrez le fichier (Ctrl+S ou Cmd+S).

  4. 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.java

    Vous ne devriez voir aucun message de sortie si la compilation réussit.

  5. Maintenant, exécutez le programme :

    java HelloJava

    Vous devriez voir la sortie suivante :

    Program finished.

    Étant donné que la ligne qui causerait la NullPointerException est 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.

  1. Ouvrez à nouveau HelloJava.java dans l'éditeur.

  2. Modifiez la méthode main pour 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 if qui vérifie si names n'est pas égal à null (names != null). Le code pour obtenir la taille et l'afficher se trouve maintenant à l'intérieur de ce bloc if, ce qui signifie qu'il ne s'exécutera que si names est un objet de liste valide. Le bloc else gère le cas où names est null.

  3. Enregistrez le fichier.

  4. Compilez le programme modifié :

    javac HelloJava.java
  5. Exécutez le programme à nouveau :

    java HelloJava

    Cette fois, vous devriez voir la sortie suivante :

    The list is null.
    Program finished.

    Le programme a correctement identifié que la liste était null et a affiché le message approprié, évitant ainsi la NullPointerException.

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.

  1. Ouvrez le fichier HelloJava.java dans l'éditeur WebIDE.

  2. 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 emptyList qui est initialisée comme une nouvelle ArrayList vide. Nous effectuons ensuite les mêmes vérifications de nullité et de vacuité sur nullList et emptyList pour voir la différence dans la sortie.

  3. Enregistrez le fichier.

  4. Compilez le programme dans le Terminal :

    javac HelloJava.java
  5. Exécutez le programme :

    java HelloJava

    Vous 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 nullList est null, tandis que emptyList n'est pas null mais 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.

  1. Ouvrez HelloJava.java dans l'éditeur.

  2. Modifiez la méthode main pour 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 conditions names == null et names.isEmpty(). Le bloc if s'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. Si names est null, 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 une NullPointerException. Si vous écriviez names.isEmpty() || names == null et que names était null, l'appel à names.isEmpty() causerait une NullPointerException. Vérifiez toujours la nullité en premier lorsque vous combinez avec d'autres vérifications sur l'objet.

  3. Enregistrez le fichier.

  4. Compilez le programme :

    javac HelloJava.java
  5. Exécutez le programme :

    java HelloJava

    Vous 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 null et 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 être null ou vides.

Utiliser Optional pour la sécurité vis - à - vis des 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>>.

  1. Ouvrez le fichier HelloJava.java dans l'éditeur WebIDE.

  2. Remplacez le contenu par le code suivant qui montre comment utiliser Optional avec 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 getNames qui retourne un Optional<List<String>>. Cette méthode simule un scénario où vous pouvez obtenir une liste ou rien du tout (représenté par un Optional vide).
    • Dans la méthode main, nous appelons getNames avec true et false pour tester les deux cas.
    • Nous utilisons namesOptional.isPresent() pour vérifier si l'Optional contient une liste.
    • Si isPresent() est vrai, nous utilisons namesOptional.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, comme names.isEmpty().
  3. Enregistrez le fichier.

  4. Compilez le programme dans le Terminal :

    javac HelloJava.java
  5. Exécutez le programme :

    java HelloJava

    Vous 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 Optional nous 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 fonction supplier.
  • orElseThrow(exceptionSupplier) : Retourne la valeur si elle est présente, sinon lance une exception produite par exceptionSupplier.
  • 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.

  1. Ouvrez HelloJava.java dans l'éditeur.

  2. Modifiez la méthode main pour utiliser ifPresent :

    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() ... } par namesOptional.ifPresent(names -> { ... }). Le code à l'intérieur de l'expression lambda (names -> { ... }) ne s'exécutera que si l'Optional contient une valeur. Nous avons toujours ajouté une vérification if (!namesOptional.isPresent()) pour gérer le cas où l'Optional est vide, car ifPresent ne gère que le cas de présence.

  3. Enregistrez le fichier.

  4. Compilez le programme :

    javac HelloJava.java
  5. Exécutez le programme :

    java HelloJava

    La sortie devrait être la même que précédemment, démontrant que ifPresent offre une autre façon de gérer la présence d'une valeur dans un Optional.

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.