Wie man prüft, ob eine Sammlung in Java null ist

JavaJavaBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab lernen Sie, wie Sie Null-Werte effektiv behandeln können, wenn Sie mit Sammlungen (Collections) in Java arbeiten. Sammlungen sind grundlegende Datenstrukturen, und es ist von entscheidender Bedeutung, robuster Code zu schreiben, der Situationen sicher bewältigen kann, in denen eine Sammlungsvariable null sein könnte. Sie werden untersuchen, wie Sie auf null-Sammlungen testen können, Null- und Leerprüfungen kombinieren können, um eine umfassende Validierung durchzuführen, und die Optional-Klasse nutzen können, um die Null-Sicherheit zu verbessern. Dies hilft Ihnen letztendlich, häufige NullPointerException-Fehler zu vermeiden.


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{{"Wie man prüft, ob eine Sammlung in Java null ist"}} java/collections_methods -.-> lab-559942{{"Wie man prüft, ob eine Sammlung in Java null ist"}} java/classes_objects -.-> lab-559942{{"Wie man prüft, ob eine Sammlung in Java null ist"}} java/exceptions -.-> lab-559942{{"Wie man prüft, ob eine Sammlung in Java null ist"}} java/arraylist -.-> lab-559942{{"Wie man prüft, ob eine Sammlung in Java null ist"}} end

Prüfen von Sammlungen auf Null

In diesem Schritt werden wir untersuchen, wie man Null-Werte behandelt, wenn man mit Sammlungen (Collections) in Java arbeitet. Sammlungen wie List oder Set sind grundlegende Datenstrukturen, und es ist von entscheidender Bedeutung, Code zu schreiben, der Situationen sicher bewältigen kann, in denen eine Sammlungsvariable null sein könnte.

Ein null-Wert in Java bedeutet, dass eine Variable auf kein Objekt verweist. Wenn Sie versuchen, Methoden oder Eigenschaften eines null-Objekts zuzugreifen, stürzt Ihr Programm mit einer NullPointerException ab. Dies ist ein sehr häufiger Fehler in Java, und es ist wichtig, zu lernen, wie man ihn vermeidet.

Beginnen wir damit, ein einfaches Java-Programm zu erstellen, das das Problem demonstriert.

  1. Öffnen Sie die Datei HelloJava.java im WebIDE-Editor, wenn sie noch nicht geöffnet ist.

  2. Ersetzen Sie den gesamten Inhalt der Datei durch folgenden Code:

    import java.util.List;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Intentionally set to null
    
            // This line will cause a NullPointerException if names is null
            // int size = names.size();
            // System.out.println("Size of the list: " + size);
    
            System.out.println("Program finished.");
        }
    }

    In diesem Code deklarieren wir eine List von Strings namens names und setzen sie explizit auf null. Die auskommentierten Zeilen zeigen, was passieren würde, wenn wir versuchen würden, die size()-Methode auf einer null-Liste aufzurufen – es würde zu einer NullPointerException führen.

  3. Speichern Sie die Datei (Strg+S oder Cmd+S).

  4. Jetzt lassen Sie uns das Programm kompilieren. Öffnen Sie das Terminal unten im WebIDE und stellen Sie sicher, dass Sie sich im Verzeichnis ~/project befinden. Führen Sie den folgenden Befehl aus:

    javac HelloJava.java

    Wenn die Kompilierung erfolgreich ist, sollten Sie keine Ausgabe sehen.

  5. Jetzt führen Sie das Programm aus:

    java HelloJava

    Sie sollten die folgende Ausgabe sehen:

    Program finished.

    Da die Zeile, die die NullPointerException verursachen würde, auskommentiert ist, läuft das Programm ohne Absturz.

Jetzt ändern wir den Code, um vor dem Verwenden der Sammlung auf null zu prüfen.

  1. Öffnen Sie HelloJava.java erneut im Editor.

  2. Ändern Sie die main-Methode, um eine Null-Prüfung einzubeziehen:

    import java.util.List;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Intentionally set to null
    
            if (names != null) {
                // This code will only run if names is NOT 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.");
        }
    }

    Wir haben eine if-Anweisung hinzugefügt, die prüft, ob names nicht gleich null ist (names != null). Der Code, um die Größe zu erhalten und sie auszugeben, befindet sich jetzt in diesem if-Block, was bedeutet, dass er nur ausgeführt wird, wenn names ein gültiges Listenobjekt ist. Der else-Block behandelt den Fall, dass names null ist.

  3. Speichern Sie die Datei.

  4. Kompilieren Sie das geänderte Programm:

    javac HelloJava.java
  5. Führen Sie das Programm erneut aus:

    java HelloJava

    Diesmal sollten Sie die folgende Ausgabe sehen:

    The list is null.
    Program finished.

    Das Programm hat korrekt erkannt, dass die Liste null war, und die entsprechende Nachricht ausgegeben, wodurch die NullPointerException vermieden wurde.

Diese einfache if (collection != null)-Prüfung ist die grundlegendste Methode, um NullPointerException bei der Arbeit mit Sammlungen zu vermeiden. Es ist eine grundlegende Technik, die Sie häufig in der Java-Programmierung verwenden werden.

Kombinieren von Null- und Leerprüfungen

Im vorherigen Schritt haben wir gelernt, wie man prüft, ob eine Sammlung (Collection) null ist. Eine Sammlung kann jedoch auch leer sein (keine Elemente enthalten), auch wenn sie nicht null ist. In vielen Fällen möchten Sie möglicherweise eine null-Sammlung und eine leere Sammlung gleich behandeln oder zumindest beide Möglichkeiten berücksichtigen.

Das Prüfen, ob eine Sammlung leer ist, erfolgt mit der Methode isEmpty(). Diese Methode gibt true zurück, wenn die Sammlung keine Elemente enthält, und false sonst.

Ändern wir unser Programm, um den Unterschied zwischen einer null-Liste und einer leeren Liste zu demonstrieren und dann die Prüfungen zu kombinieren.

  1. Öffnen Sie die Datei HelloJava.java im WebIDE-Editor.

  2. Ersetzen Sie den Inhalt durch folgenden Code:

    import java.util.List;
    import java.util.ArrayList; // Import ArrayList
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> nullList = null; // Intentionally set to null
            List<String> emptyList = new ArrayList<>(); // An empty list
    
            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.");
        }
    }

    Wir haben eine emptyList hinzugefügt, die als neue, leere ArrayList initialisiert wird. Anschließend führen wir die gleichen Null- und Leerprüfungen sowohl für nullList als auch für emptyList durch, um den Unterschied in der Ausgabe zu sehen.

  3. Speichern Sie die Datei.

  4. Kompilieren Sie das Programm im Terminal:

    javac HelloJava.java
  5. Führen Sie das Programm aus:

    java HelloJava

    Sie sollten eine Ausgabe ähnlich der folgenden sehen:

    Checking nullList:
    nullList is null.
    
    Checking emptyList:
    emptyList is not null.
    emptyList is empty.
    
    Program finished.

    Diese Ausgabe zeigt deutlich, dass nullList null ist, während emptyList nicht null ist, aber leer ist.

Jetzt kombinieren wir die Null- und Leerprüfungen zu einer einzigen Bedingung. Ein häufiges Muster ist es, zu prüfen, ob eine Sammlung entweder null oder leer ist.

  1. Öffnen Sie HelloJava.java im Editor.

  2. Ändern Sie die main-Methode, um die Prüfungen zu kombinieren:

    import java.util.List;
    import java.util.ArrayList;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Can be null or an empty list
    
            // Combined check: is names null OR is names empty?
            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.");
                // You can safely iterate or access elements here
                // For example:
                // System.out.println("First element: " + names.get(0));
            }
    
            // Let's test with an empty list
            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.");
            }
    
            // Let's test with a non-empty list
            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.");
        }
    }

    Wir verwenden den logischen ODER-Operator (||), um die Bedingungen names == null und names.isEmpty() zu kombinieren. Der if-Block wird ausgeführt, wenn eine der Bedingungen wahr ist. Wir haben auch Tests mit einer leeren Liste und einer gefüllten Liste hinzugefügt, um zu sehen, wie die kombinierte Prüfung funktioniert.

    Wichtiger Hinweis: Die Reihenfolge der Bedingungen in names == null || names.isEmpty() ist von entscheidender Bedeutung. Wenn names null ist, ist der erste Teil der Bedingung (names == null) wahr. Aufgrund der Kurzschlussauswertung in Java wird der zweite Teil (names.isEmpty()) nicht ausgewertet, wodurch eine NullPointerException vermieden wird. Wenn Sie names.isEmpty() || names == null schreiben und names null wäre, würde der Aufruf von names.isEmpty() eine NullPointerException verursachen. Prüfen Sie immer zuerst auf null, wenn Sie mit anderen Prüfungen am Objekt kombinieren.

  3. Speichern Sie die Datei.

  4. Kompilieren Sie das Programm:

    javac HelloJava.java
  5. Führen Sie das Programm aus:

    java HelloJava

    Sie sollten eine Ausgabe ähnlich der folgenden sehen:

    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.

    Dies zeigt, wie die kombinierte Prüfung null- und leere Listen korrekt erkennt und sie von nicht-leeren Listen unterscheidet. Diese kombinierte Prüfung ist eine sehr häufige und sichere Methode, um Sammlungen zu behandeln, die null oder leer sein könnten.

Verwendung von Optional für Null-Sicherheit

In diesem Schritt werden wir einen moderneren Ansatz zur Behandlung potenzieller null-Werte in Java mithilfe der Optional-Klasse untersuchen, die in Java 8 eingeführt wurde. Optional ist ein Containerobjekt, das einen nicht-null-Wert enthalten kann oder auch nicht. Es bietet eine Möglichkeit, das Vorhandensein oder Fehlen eines Werts deutlicher darzustellen, was dazu beitragen kann, das Risiko von NullPointerExceptions zu verringern.

Während if (collection != null)-Prüfungen in vielen Situationen völlig gültig und notwendig sind, kann Optional Ihren Code lesbarer und ausdrucksstärker machen, insbesondere wenn es um Methoden geht, die einen Wert zurückgeben können oder auch null zurückgeben können.

Schauen wir uns an, wie wir Optional mit einer Sammlung verwenden können. Obwohl Optional typischerweise für einzelne Werte verwendet wird, können Sie Szenarien antreffen, in denen eine Methode ein Optional<List<SomeObject>> zurückgibt.

  1. Öffnen Sie die Datei HelloJava.java im WebIDE-Editor.

  2. Ersetzen Sie den Inhalt durch folgenden Code, der die Verwendung von Optional mit einer potenziell null-Liste demonstriert:

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Optional; // Import Optional
    
    public class HelloJava {
    
        // A method that might return an Optional containing a list, or an empty Optional
        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); // Return an Optional containing the list
            } else {
                return Optional.empty(); // Return an empty Optional
            }
        }
    
        public static void main(String[] args) {
            // Case 1: Get names when includeNames is true
            Optional<List<String>> namesOptional1 = getNames(true);
    
            System.out.println("Checking namesOptional1:");
            // Check if the Optional contains a value
            if (namesOptional1.isPresent()) {
                List<String> names = namesOptional1.get(); // Get the list from the Optional
                System.out.println("List is present. Size: " + names.size());
                // You can also check if the list itself is empty
                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("---");
    
            // Case 2: Get names when includeNames is 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.");
        }
    }

    In diesem Code:

    • Wir definieren eine Methode getNames, die ein Optional<List<String>> zurückgibt. Diese Methode simuliert ein Szenario, in dem Sie eine Liste erhalten können oder auch nichts (repräsentiert durch ein leeres Optional).
    • In der main-Methode rufen wir getNames mit true und false auf, um beide Fälle zu testen.
    • Wir verwenden namesOptional.isPresent(), um zu prüfen, ob das Optional eine Liste enthält.
    • Wenn isPresent() true ist, verwenden wir namesOptional.get(), um die Liste abzurufen. Dies ist sicher, da wir bereits auf das Vorhandensein geprüft haben.
    • Innerhalb des isPresent()-Blocks können wir dann Prüfungen an der Liste selbst durchführen, wie z. B. names.isEmpty().
  3. Speichern Sie die Datei.

  4. Kompilieren Sie das Programm im Terminal:

    javac HelloJava.java
  5. Führen Sie das Programm aus:

    java HelloJava

    Sie sollten eine Ausgabe ähnlich der folgenden sehen:

    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.

    Diese Ausgabe zeigt, wie Optional uns hilft, den Fall zu behandeln, in dem eine Liste überhaupt nicht zurückgegeben wird.

Optional bietet auch andere nützliche Methoden zur Behandlung des Fehlens eines Werts, wie z. B.:

  • orElse(defaultValue): Gibt den Wert zurück, wenn er vorhanden ist, andernfalls einen Standardwert.
  • orElseGet(supplier): Gibt den Wert zurück, wenn er vorhanden ist, andernfalls das Ergebnis der supplier-Funktion.
  • orElseThrow(exceptionSupplier): Gibt den Wert zurück, wenn er vorhanden ist, andernfalls wirft es eine Ausnahme, die von der exceptionSupplier-Funktion erzeugt wird.
  • ifPresent(consumer): Führt die angegebene Aktion aus, wenn ein Wert vorhanden ist.

Ändern wir den Code, um ifPresent zu verwenden, um die Liste auf eine kompaktere Weise zu behandeln, wenn sie vorhanden ist.

  1. Öffnen Sie HelloJava.java im Editor.

  2. Ändern Sie die main-Methode, um ifPresent zu verwenden:

    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) {
            // Case 1: Get names when includeNames is true
            Optional<List<String>> namesOptional1 = getNames(true);
    
            System.out.println("Checking namesOptional1 using ifPresent:");
            namesOptional1.ifPresent(names -> {
                // This block only runs if namesOptional1 contains a list
                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()) { // Still need a check if you need to handle the absence case
                 System.out.println("List is not present (Optional is empty).");
            }
    
    
            System.out.println("---");
    
            // Case 2: Get names when includeNames is 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.");
        }
    }

    Wir haben die Struktur if (namesOptional.isPresent()) { ... namesOptional.get() ... } durch namesOptional.ifPresent(names -> { ... }) ersetzt. Der Code innerhalb des Lambda-Ausdrucks (names -> { ... }) wird nur ausgeführt, wenn das Optional einen Wert enthält. Wir haben weiterhin eine if (!namesOptional.isPresent())-Prüfung hinzugefügt, um den Fall zu behandeln, in dem das Optional leer ist, da ifPresent nur den Fall des Vorhandenseins behandelt.

  3. Speichern Sie die Datei.

  4. Kompilieren Sie das Programm:

    javac HelloJava.java
  5. Führen Sie das Programm aus:

    java HelloJava

    Die Ausgabe sollte die gleiche wie zuvor sein, was zeigt, dass ifPresent eine alternative Möglichkeit bietet, das Vorhandensein eines Werts in einem Optional zu behandeln.

Die Verwendung von Optional kann die Absicht Ihres Codes dahingehend klarer machen, ob ein Wert fehlen kann, und es ermutigt Sie, dieses Fehlen explizit zu behandeln, wodurch die Wahrscheinlichkeit unerwarteter NullPointerExceptions verringert wird.

Zusammenfassung

In diesem Lab haben wir gelernt, wie man Null-Sammlungen (null collections) in Java behandelt, um NullPointerException zu vermeiden. Wir haben zunächst das Problem demonstriert, das entsteht, wenn man Methoden auf einer Null-Sammlung aufruft, was zu einem Laufzeitfehler führt.

Anschließend haben wir verschiedene Techniken untersucht, um sicherzustellen, dass eine Sammlung nicht null ist, bevor man versucht, auf ihre Elemente oder Eigenschaften zuzugreifen. Dies ist eine grundlegende Fähigkeit für das Schreiben von robustem und fehlerfreiem Java-Code.