Cómo comprobar si una colección es nula en Java

JavaJavaBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, aprenderás cómo manejar de manera efectiva los valores nulos cuando trabajes con colecciones en Java. Las colecciones son estructuras de datos fundamentales, y es crucial escribir código robusto que pueda manejar de forma segura situaciones en las que una variable de colección podría ser nula. Explorarás cómo probar si una colección es nula, combinar comprobaciones de nulidad y vacío para una validación integral, y aprovechar la clase Optional para una mayor seguridad frente a valores nulos, lo que en última instancia te ayudará a evitar los errores comunes 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{{"Cómo comprobar si una colección es nula en Java"}} java/collections_methods -.-> lab-559942{{"Cómo comprobar si una colección es nula en Java"}} java/classes_objects -.-> lab-559942{{"Cómo comprobar si una colección es nula en Java"}} java/exceptions -.-> lab-559942{{"Cómo comprobar si una colección es nula en Java"}} java/arraylist -.-> lab-559942{{"Cómo comprobar si una colección es nula en Java"}} end

Probar si una colección es nula

En este paso, exploraremos cómo manejar valores nulos cuando trabajamos con colecciones en Java. Las colecciones, como List o Set, son estructuras de datos fundamentales, y es crucial escribir código que pueda manejar de forma segura situaciones en las que una variable de colección podría ser null.

Un valor null en Java significa que una variable no se refiere a ningún objeto. Si intentas acceder a métodos o propiedades de un objeto null, tu programa se detendrá con un NullPointerException. Este es un error muy común en Java, y aprender a evitarlo es esencial.

Comencemos creando un simple programa en Java que demuestre el problema.

  1. Abre el archivo HelloJava.java en el editor WebIDE si no está abierto.

  2. Reemplaza todo el contenido del archivo con el siguiente código:

    import java.util.List;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Intencionalmente establecido en null
    
            // Esta línea causará un NullPointerException si names es null
            // int size = names.size();
            // System.out.println("Tamaño de la lista: " + size);
    
            System.out.println("Programa finalizado.");
        }
    }

    En este código, declaramos una List de cadenas llamada names y la establecemos explícitamente en null. Las líneas comentadas muestran lo que sucedería si intentáramos llamar al método size() en una lista null – resultaría en un NullPointerException.

  3. Guarda el archivo (Ctrl+S o Cmd+S).

  4. Ahora, compilemos el programa. Abre la Terminal en la parte inferior del WebIDE y asegúrate de estar en el directorio ~/project. Ejecuta el siguiente comando:

    javac HelloJava.java

    No deberías ver salida alguna si la compilación es exitosa.

  5. Ahora, ejecuta el programa:

    java HelloJava

    Deberías ver la salida:

    Programa finalizado.

    Dado que la línea que causaría el NullPointerException está comentada, el programa se ejecuta sin detenerse.

Ahora, modifiquemos el código para comprobar si es null antes de intentar usar la colección.

  1. Abre HelloJava.java nuevamente en el editor.

  2. Modifica el método main para incluir una comprobación de nulidad:

    import java.util.List;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Intencionalmente establecido en null
    
            if (names != null) {
                // Este código solo se ejecutará si names NO es null
                int size = names.size();
                System.out.println("Tamaño de la lista: " + size);
            } else {
                System.out.println("La lista es null.");
            }
    
            System.out.println("Programa finalizado.");
        }
    }

    Hemos agregado una instrucción if que comprueba si names no es igual a null (names != null). El código para obtener el tamaño y mostrarlo ahora está dentro de este bloque if, lo que significa que solo se ejecutará si names es un objeto de lista válido. El bloque else maneja el caso en el que names es null.

  3. Guarda el archivo.

  4. Compila el programa modificado:

    javac HelloJava.java
  5. Ejecuta el programa nuevamente:

    java HelloJava

    Esta vez, deberías ver la salida:

    La lista es null.
    Programa finalizado.

    El programa identificó correctamente que la lista era null y mostró el mensaje adecuado, evitando el NullPointerException.

Esta simple comprobación if (collection != null) es la forma más básica de prevenir NullPointerException cuando se trabaja con colecciones. Es una técnica fundamental que usarás con frecuencia en la programación en Java.

Combinar comprobaciones de nulidad y vacío

En el paso anterior, aprendimos cómo comprobar si una colección es null. Sin embargo, una colección también puede estar vacía (no contener elementos) incluso si no es null. En muchos casos, es posible que desees tratar de manera similar una colección null y una colección vacía, o al menos manejar ambas posibilidades.

Comprobar si una colección está vacía se hace utilizando el método isEmpty(). Este método devuelve true si la colección no contiene elementos y false en caso contrario.

Modifiquemos nuestro programa para demostrar la diferencia entre una lista null y una lista vacía, y luego combinemos las comprobaciones.

  1. Abre el archivo HelloJava.java en el editor WebIDE.

  2. Reemplaza el contenido con el siguiente código:

    import java.util.List;
    import java.util.ArrayList; // Import ArrayList
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> nullList = null; // Intencionalmente establecido en null
            List<String> emptyList = new ArrayList<>(); // Una lista vacía
    
            System.out.println("Comprobando nullList:");
            if (nullList != null) {
                System.out.println("nullList no es null.");
                if (nullList.isEmpty()) {
                    System.out.println("nullList está vacía.");
                } else {
                    System.out.println("nullList no está vacía.");
                }
            } else {
                System.out.println("nullList es null.");
            }
    
            System.out.println("\nComprobando emptyList:");
            if (emptyList != null) {
                System.out.println("emptyList no es null.");
                if (emptyList.isEmpty()) {
                    System.out.println("emptyList está vacía.");
                } else {
                    System.out.println("emptyList no está vacía.");
                }
            } else {
                System.out.println("emptyList es null.");
            }
    
            System.out.println("\nPrograma finalizado.");
        }
    }

    Hemos agregado una emptyList que se inicializa como una nueva ArrayList vacía. Luego, realizamos las mismas comprobaciones de nulidad y vacío en nullList y emptyList para ver la diferencia en la salida.

  3. Guarda el archivo.

  4. Compila el programa en la Terminal:

    javac HelloJava.java
  5. Ejecuta el programa:

    java HelloJava

    Deberías ver una salida similar a esta:

    Comprobando nullList:
    nullList es null.
    
    Comprobando emptyList:
    emptyList no es null.
    emptyList está vacía.
    
    Programa finalizado.

    Esta salida muestra claramente que nullList es null, mientras que emptyList no es null pero está vacía.

Ahora, combinemos las comprobaciones de nulidad y vacío en una sola condición. Un patrón común es comprobar si una colección es null o está vacía.

  1. Abre HelloJava.java en el editor.

  2. Modifica el método main para combinar las comprobaciones:

    import java.util.List;
    import java.util.ArrayList;
    
    public class HelloJava {
        public static void main(String[] args) {
            List<String> names = null; // Puede ser null o una lista vacía
    
            // Comprobación combinada: ¿es names null O está names vacía?
            if (names == null || names.isEmpty()) {
                System.out.println("La lista es null o está vacía.");
            } else {
                System.out.println("La lista no es null y no está vacía.");
                // Puedes iterar o acceder a los elementos de forma segura aquí
                // Por ejemplo:
                // System.out.println("Primer elemento: " + names.get(0));
            }
    
            // Probemos con una lista vacía
            List<String> anotherList = new ArrayList<>();
            System.out.println("\nComprobando anotherList (vacía):");
            if (anotherList == null || anotherList.isEmpty()) {
                System.out.println("anotherList es null o está vacía.");
            } else {
                System.out.println("anotherList no es null y no está vacía.");
            }
    
            // Probemos con una lista no vacía
            List<String> populatedList = new ArrayList<>();
            populatedList.add("Item 1");
            System.out.println("\nComprobando populatedList (no vacía):");
            if (populatedList == null || populatedList.isEmpty()) {
                System.out.println("populatedList es null o está vacía.");
            } else {
                System.out.println("populatedList no es null y no está vacía.");
            }
    
    
            System.out.println("\nPrograma finalizado.");
        }
    }

    Usamos el operador lógico OR (||) para combinar las condiciones names == null y names.isEmpty(). El bloque if se ejecutará si cualquiera de las condiciones es verdadera. También agregamos pruebas con una lista vacía y una lista con elementos para ver cómo se comporta la comprobación combinada.

    Nota importante: El orden de las condiciones en names == null || names.isEmpty() es crucial. Si names es null, la primera parte de la condición (names == null) es verdadera. Debido a la evaluación de cortocircuito en Java, la segunda parte (names.isEmpty()) no se evalúa, evitando un NullPointerException. Si escribieras names.isEmpty() || names == null, y names fuera null, llamar a names.isEmpty() causaría un NullPointerException. Siempre comprueba si es null primero cuando combinas con otras comprobaciones en el objeto.

  3. Guarda el archivo.

  4. Compila el programa:

    javac HelloJava.java
  5. Ejecuta el programa:

    java HelloJava

    Deberías ver una salida similar a esta:

    La lista es null o está vacía.
    
    Comprobando anotherList (vacía):
    anotherList es null o está vacía.
    
    Comprobando populatedList (no vacía):
    populatedList no es null y no está vacía.
    
    Programa finalizado.

    Esto demuestra cómo la comprobación combinada identifica correctamente las listas null y vacías, y las distingue de las listas no vacías. Esta comprobación combinada es una forma muy común y segura de manejar colecciones que pueden ser null o vacías.

Utilizar Optional para seguridad frente a valores nulos

En este paso, exploraremos un enfoque más moderno para manejar posibles valores null en Java utilizando la clase Optional, introducida en Java 8. Optional es un objeto contenedor que puede o no contener un valor no nulo. Proporciona una forma de representar de manera más explícita la presencia o ausencia de un valor, lo que puede ayudar a reducir el riesgo de NullPointerException.

Si bien las comprobaciones if (collection != null) son perfectamente válidas y necesarias en muchas situaciones, Optional puede hacer que tu código sea más legible y expresivo, especialmente cuando se trata de métodos que pueden devolver un valor o pueden devolver null.

Veamos cómo podemos utilizar Optional con una colección. Aunque Optional se utiliza típicamente para valores individuales, es posible que encuentres escenarios en los que un método devuelva un Optional<List<SomeObject>>.

  1. Abre el archivo HelloJava.java en el editor WebIDE.

  2. Reemplaza el contenido con el siguiente código que demuestra el uso de Optional con una lista potencialmente nula:

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Optional; // Import Optional
    
    public class HelloJava {
    
        // Un método que puede devolver un Optional que contiene una lista, o un Optional vacío
        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); // Devuelve un Optional que contiene la lista
            } else {
                return Optional.empty(); // Devuelve un Optional vacío
            }
        }
    
        public static void main(String[] args) {
            // Caso 1: Obtener nombres cuando includeNames es true
            Optional<List<String>> namesOptional1 = getNames(true);
    
            System.out.println("Comprobando namesOptional1:");
            // Comprobar si el Optional contiene un valor
            if (namesOptional1.isPresent()) {
                List<String> names = namesOptional1.get(); // Obtener la lista del Optional
                System.out.println("La lista está presente. Tamaño: " + names.size());
                // También puedes comprobar si la lista en sí está vacía
                if (names.isEmpty()) {
                    System.out.println("La lista está vacía.");
                } else {
                    System.out.println("La lista no está vacía. Primer nombre: " + names.get(0));
                }
            } else {
                System.out.println("La lista no está presente (Optional está vacío).");
            }
    
            System.out.println("---");
    
            // Caso 2: Obtener nombres cuando includeNames es false
            Optional<List<String>> namesOptional2 = getNames(false);
    
            System.out.println("Comprobando namesOptional2:");
            if (namesOptional2.isPresent()) {
                List<String> names = namesOptional2.get();
                System.out.println("La lista está presente. Tamaño: " + names.size());
                if (names.isEmpty()) {
                    System.out.println("La lista está vacía.");
                } else {
                    System.out.println("La lista no está vacía. Primer nombre: " + names.get(0));
                }
            } else {
                System.out.println("La lista no está presente (Optional está vacío).");
            }
    
    
            System.out.println("\nPrograma finalizado.");
        }
    }

    En este código:

    • Definimos un método getNames que devuelve un Optional<List<String>>. Este método simula un escenario en el que puedes obtener una lista o no obtener nada (representado por un Optional vacío).
    • En el método main, llamamos a getNames con true y false para probar ambos casos.
    • Usamos namesOptional.isPresent() para comprobar si el Optional contiene una lista.
    • Si isPresent() es verdadero, usamos namesOptional.get() para recuperar la lista. Esto es seguro porque ya hemos comprobado la presencia.
    • Dentro del bloque isPresent(), luego podemos realizar comprobaciones en la lista en sí, como names.isEmpty().
  3. Guarda el archivo.

  4. Compila el programa en la Terminal:

    javac HelloJava.java
  5. Ejecuta el programa:

    java HelloJava

    Deberías ver una salida similar a esta:

    Comprobando namesOptional1:
    La lista está presente. Tamaño: 2
    La lista no está vacía. Primer nombre: Alice
    ---
    Comprobando namesOptional2:
    La lista no está presente (Optional está vacío).
    
    Programa finalizado.

    Esta salida muestra cómo Optional nos ayuda a manejar el caso en el que una lista puede no ser devuelta en absoluto.

Optional también proporciona otros métodos útiles para manejar la ausencia de un valor, como:

  • orElse(defaultValue): Devuelve el valor si está presente, de lo contrario devuelve un valor predeterminado.
  • orElseGet(supplier): Devuelve el valor si está presente, de lo contrario devuelve el resultado de la función supplier.
  • orElseThrow(exceptionSupplier): Devuelve el valor si está presente, de lo contrario lanza una excepción producida por el exceptionSupplier.
  • ifPresent(consumer): Realiza la acción dada si un valor está presente.

Modifiquemos el código para usar ifPresent de una manera más concisa para manejar la lista cuando está presente.

  1. Abre HelloJava.java en el editor.

  2. Modifica el método main para usar 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) {
            // Caso 1: Obtener nombres cuando includeNames es true
            Optional<List<String>> namesOptional1 = getNames(true);
    
            System.out.println("Comprobando namesOptional1 usando ifPresent:");
            namesOptional1.ifPresent(names -> {
                // Este bloque solo se ejecuta si namesOptional1 contiene una lista
                System.out.println("La lista está presente. Tamaño: " + names.size());
                if (names.isEmpty()) {
                    System.out.println("La lista está vacía.");
                } else {
                    System.out.println("La lista no está vacía. Primer nombre: " + names.get(0));
                }
            });
            if (!namesOptional1.isPresent()) { // Todavía se necesita una comprobación si se debe manejar el caso de ausencia
                 System.out.println("La lista no está presente (Optional está vacío).");
            }
    
    
            System.out.println("---");
    
            // Caso 2: Obtener nombres cuando includeNames es false
            Optional<List<String>> namesOptional2 = getNames(false);
    
            System.out.println("Comprobando namesOptional2 usando ifPresent:");
             namesOptional2.ifPresent(names -> {
                System.out.println("La lista está presente. Tamaño: " + names.size());
                if (names.isEmpty()) {
                    System.out.println("La lista está vacía.");
                } else {
                    System.out.println("La lista no está vacía. Primer nombre: " + names.get(0));
                }
            });
             if (!namesOptional2.isPresent()) {
                 System.out.println("La lista no está presente (Optional está vacío).");
             }
    
    
            System.out.println("\nPrograma finalizado.");
        }
    }

    Reemplazamos la estructura if (namesOptional.isPresent()) { ... namesOptional.get() ... } con namesOptional.ifPresent(names -> { ... }). El código dentro de la expresión lambda (names -> { ... }) solo se ejecutará si el Optional contiene un valor. Todavía agregamos una comprobación if (!namesOptional.isPresent()) para manejar el caso en el que el Optional está vacío, ya que ifPresent solo maneja el caso de presencia.

  3. Guarda el archivo.

  4. Compila el programa:

    javac HelloJava.java
  5. Ejecuta el programa:

    java HelloJava

    La salida debe ser la misma que antes, lo que demuestra que ifPresent proporciona una forma alternativa de manejar la presencia de un valor en un Optional.

Utilizar Optional puede hacer que la intención de tu código sea más clara en cuanto a si un valor puede estar ausente, y te anima a manejar esa ausencia de manera explícita, reduciendo la probabilidad de NullPointerException inesperados.

Resumen

En este laboratorio (lab), aprendimos cómo manejar colecciones nulas en Java para prevenir NullPointerException. Comenzamos demostrando el problema de llamar a métodos en una colección nula, lo cual conduce a un error en tiempo de ejecución.

Luego exploramos diferentes técnicas para comprobar de manera segura si una colección es nula antes de intentar acceder a sus elementos o propiedades. Esta es una habilidad fundamental para escribir código Java robusto y libre de errores.