Cómo verificar si dos objetos son iguales 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 verificar si dos objetos son iguales en Java. Exploraremos la diferencia fundamental entre usar el operador == y el método equals() para la comparación de objetos.

Comenzarás utilizando el método equals() incorporado para comparar objetos y entender su comportamiento con diferentes tipos de datos. Luego, aprenderás cómo sobrescribir el método equals() en tus propias clases personalizadas para definir qué constituye la igualdad lógica de tus objetos. Finalmente, abordarás la importante consideración de manejar objetos nulos al realizar comprobaciones de igualdad para prevenir posibles errores de NullPointerException.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/ProgrammingTechniquesGroup(["Programming Techniques"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java(("Java")) -.-> java/StringManipulationGroup(["String Manipulation"]) java/StringManipulationGroup -.-> java/strings("Strings") java/ProgrammingTechniquesGroup -.-> java/method_overriding("Method Overriding") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects") java/SystemandDataProcessingGroup -.-> java/object_methods("Object Methods") subgraph Lab Skills java/strings -.-> lab-560013{{"Cómo verificar si dos objetos son iguales en Java"}} java/method_overriding -.-> lab-560013{{"Cómo verificar si dos objetos son iguales en Java"}} java/classes_objects -.-> lab-560013{{"Cómo verificar si dos objetos son iguales en Java"}} java/object_methods -.-> lab-560013{{"Cómo verificar si dos objetos son iguales en Java"}} end

Usar el método equals() para la igualdad

En este paso, exploraremos cómo comparar objetos en Java utilizando el método equals(). Mientras que el operador == verifica si dos referencias de objetos apuntan al mismo objeto exacto en la memoria, el método equals() está diseñado para verificar si dos objetos son lógicamente iguales, lo que significa que representan el mismo valor o estado.

Comencemos creando un sencillo archivo Java para demostrar este concepto.

  1. Abre el WebIDE y asegúrate de estar en el directorio ~/project. Puedes confirmar esto mirando el indicador del terminal o escribiendo pwd y presionando Enter.

  2. Crea un nuevo archivo llamado EqualityDemo.java en el directorio ~/project. Puedes hacer esto haciendo clic derecho en el Explorador de archivos de la izquierda y seleccionando "Nuevo archivo", luego escribiendo EqualityDemo.java.

  3. Abre el archivo EqualityDemo.java en el editor y pega el siguiente código:

    public class EqualityDemo {
        public static void main(String[] args) {
            String str1 = new String("hello");
            String str2 = new String("hello");
            String str3 = str1;
    
            System.out.println("Comparing String objects:");
            System.out.println("str1 == str2: " + (str1 == str2));
            System.out.println("str1.equals(str2): " + str1.equals(str2));
            System.out.println("str1 == str3: " + (str1 == str3));
            System.out.println("str1.equals(str3): " + str1.equals(str3));
    
            System.out.println("\nComparing primitive types (int):");
            int num1 = 10;
            int num2 = 10;
            System.out.println("num1 == num2: " + (num1 == num2));
        }
    }

    En este código:

    • Creamos dos objetos String, str1 y str2, con el mismo contenido ("hello") pero utilizando new String(), lo que crea objetos distintos en la memoria.
    • Creamos una tercera referencia String, str3, y la hacemos apuntar al mismo objeto que str1.
    • Utilizamos tanto == como equals() para comparar str1 y str2, y str1 y str3.
    • También mostramos una comparación de tipos primitivos int utilizando ==. Recuerda que equals() se utiliza para objetos, no para tipos primitivos.
  4. Guarda el archivo EqualityDemo.java (Ctrl+S o Cmd+S).

  5. Abre la Terminal en la parte inferior del WebIDE.

  6. Compila el programa Java escribiendo el siguiente comando y presionando Enter:

    javac EqualityDemo.java

    Si no hay errores, no deberías ver salida alguna.

  7. Ejecuta el programa compilado escribiendo el siguiente comando y presionando Enter:

    java EqualityDemo

    Deberías ver una salida similar a esta:

    Comparing String objects:
    str1 == str2: false
    str1.equals(str2): true
    str1 == str3: true
    str1.equals(str3): true
    
    Comparing primitive types (int):
    num1 == num2: true

    Observa que str1 == str2 es false porque son objetos diferentes en la memoria, aunque tengan el mismo contenido. Sin embargo, str1.equals(str2) es true porque el método equals() de la clase String está sobrescrito para comparar el contenido real de las cadenas. str1 == str3 es true porque str3 apunta al mismo objeto exacto que str1.

Esto demuestra la diferencia clave entre == (igualdad de referencia) y equals() (igualdad lógica) al comparar objetos en Java. Para tipos primitivos, == se utiliza para la comparación de valores.

Sobrescribir el método equals() en una clase personalizada

En el paso anterior, vimos cómo funciona el método equals() para objetos String. La clase String ya ha sobrescrito el método equals() predeterminado (heredado de la clase Object) para proporcionar una comparación significativa basada en el contenido.

Sin embargo, cuando creas tus propias clases personalizadas, el método equals() predeterminado heredado de Object simplemente utiliza el operador ==, lo que significa que solo verifica la igualdad de referencia. Para comparar objetos de tu clase personalizada en función de sus atributos (igualdad lógica), debes sobrescribir el método equals() tú mismo.

En este paso, crearemos una sencilla clase Person y sobrescribiremos su método equals().

  1. Asegúrate de estar en el directorio ~/project en el WebIDE.

  2. Crea un nuevo archivo llamado Person.java en el directorio ~/project.

  3. Abre Person.java y pega el siguiente código para la clase Person:

    public class Person {
        private String name;
        private int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    
        // Default equals() method (inherited from Object) would only check reference equality
        // We need to override it to check for logical equality based on name and age
        @Override
        public boolean equals(Object obj) {
            // Step 1: Check if the objects are the same instance
            if (this == obj) {
                return true;
            }
    
            // Step 2: Check if the object is null or of a different class
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
    
            // Step 3: Cast the object to the correct type
            Person person = (Person) obj;
    
            // Step 4: Compare the relevant attributes
            return age == person.age &&
                   name.equals(person.name); // Use equals() for String comparison
        }
    }

    En esta clase Person:

    • Tenemos dos atributos privados: name (cadena) y age (entero).
    • Tenemos un constructor para inicializar estos atributos.
    • Tenemos métodos getter para acceder a los atributos.
    • Hemos sobrescrito el método equals(). Veamos los pasos dentro del método equals() sobrescrito:
      • if (this == obj): Esta es una optimización. Si las dos referencias apuntan al mismo objeto exacto, definitivamente son iguales.
      • if (obj == null || getClass() != obj.getClass()): Esto verifica si el objeto con el que se está comparando es nulo o si no es una instancia de la clase Person. Si cualquiera de estas condiciones es verdadera, no pueden ser iguales.
      • Person person = (Person) obj;: Convertimos el objeto genérico Object a un objeto Person para poder acceder a sus atributos name y age.
      • return age == person.age && name.equals(person.name);: Este es el núcleo de la comparación lógica. Verificamos si la edad es la misma (utilizando == para enteros primitivos) y si el nombre es el mismo (utilizando equals() para objetos String).
  4. Guarda el archivo Person.java.

  5. Ahora, creemos otro archivo, PersonEqualityDemo.java, para probar nuestro método equals() sobrescrito. Crea este archivo en el directorio ~/project.

  6. Abre PersonEqualityDemo.java y pega el siguiente código:

    public class PersonEqualityDemo {
        public static void main(String[] args) {
            Person person1 = new Person("Alice", 30);
            Person person2 = new Person("Alice", 30);
            Person person3 = new Person("Bob", 25);
            Person person4 = person1;
    
            System.out.println("Comparing Person objects:");
            System.out.println("person1 == person2: " + (person1 == person2));
            System.out.println("person1.equals(person2): " + person1.equals(person2));
            System.out.println("person1 == person3: " + (person1 == person3));
            System.out.println("person1.equals(person3): " + person1.equals(person3));
            System.out.println("person1 == person4: " + (person1 == person4));
            System.out.println("person1.equals(person4): " + person1.equals(person4));
        }
    }

    En esta clase de demostración, creamos varios objetos Person y los comparamos utilizando tanto == como nuestro método equals() sobrescrito.

  7. Guarda el archivo PersonEqualityDemo.java.

  8. Abre la Terminal. Asegúrate de estar en ~/project.

  9. Compila ambos archivos Java. Puedes compilar múltiples archivos a la vez:

    javac Person.java PersonEqualityDemo.java

    Esto debería crear los archivos Person.class y PersonEqualityDemo.class.

  10. Ejecuta el programa de demostración:

    java PersonEqualityDemo

    Deberías ver una salida similar a esta:

    Comparing Person objects:
    person1 == person2: false
    person1.equals(person2): true
    person1 == person3: false
    person1.equals(person3): false
    person1 == person4: true
    person1.equals(person4): true

    Como se esperaba, person1 == person2 es false porque son objetos distintos, pero person1.equals(person2) es true porque su nombre y edad son los mismos según nuestro método sobrescrito. person1 y person3 no son iguales en ninguna de las comparaciones. person1 y person4 son iguales en ambas comparaciones porque se refieren al mismo objeto.

Al sobrescribir el método equals(), defines lo que significa "igual" para objetos de tu clase personalizada en función de su estado lógico en lugar de solo su ubicación en memoria.

Manejar objetos nulos en la igualdad

En el paso anterior, sobrescribimos con éxito el método equals() en nuestra clase Person para comparar objetos en función de sus atributos. Un aspecto crucial al escribir métodos equals() robustos es manejar los posibles valores null. Si intentas llamar a un método en un objeto null, se producirá una NullPointerException, que es un error común en Java.

Nuestro método equals() sobrescrito en Person.java ya incluye una comprobación para null: if (obj == null || getClass() != obj.getClass()). Esta es la forma estándar de manejar el caso en el que el objeto con el que se está comparando es null.

En este paso, demostraremos lo que sucede cuando se compara un objeto con null y confirmaremos que nuestro método equals() lo maneja correctamente.

  1. Asegúrate de estar en el directorio ~/project en el WebIDE.

  2. Abre el archivo PersonEqualityDemo.java que creaste en el paso anterior.

  3. Agrega las siguientes líneas al método main, después de las declaraciones de comparación existentes:

    System.out.println("\nComparing with null:");
    System.out.println("person1.equals(null): " + person1.equals(null));

    Este código simplemente agrega una comparación de person1 con null.

  4. Guarda el archivo PersonEqualityDemo.java.

  5. Abre la Terminal. Asegúrate de estar en ~/project.

  6. Compila el archivo PersonEqualityDemo.java modificado:

    javac PersonEqualityDemo.java

    Recuerda que solo necesitas recompilar los archivos que has modificado. Dado que Person.java no se modificó en este paso, solo necesitamos compilar PersonEqualityDemo.java.

  7. Ejecuta el programa compilado:

    java PersonEqualityDemo

    Ahora deberías ver la salida anterior seguida de la nueva comparación con null:

    Comparing Person objects:
    person1 == person2: false
    person1.equals(person2): true
    person1 == person3: false
    person1.equals(person3): false
    person1 == person4: true
    person1.equals(person4): true
    
    Comparing with null:
    person1.equals(null): false

    La salida person1.equals(null): false confirma que nuestro método equals() sobrescrito maneja correctamente la comparación con null y devuelve false sin lanzar una NullPointerException. Esto se debe a que la línea if (obj == null || getClass() != obj.getClass()) en el método equals() de nuestra clase Person comprueba si es null antes de intentar acceder a cualquier atributo de obj.

Manejar null es una parte crítica al escribir código robusto en Java, especialmente cuando se trata de comparaciones de objetos. Siempre incluye una comprobación de null al principio de tu método equals() sobrescrito.

Resumen

En este laboratorio, aprendimos cómo verificar si dos objetos son iguales en Java. Comenzamos por entender la diferencia entre el operador ==, que verifica la igualdad de referencia, y el método equals(), que verifica la igualdad lógica. Demostramos esto utilizando objetos String y tipos primitivos, observando cómo == se comporta de manera diferente a equals() para objetos.

Luego exploramos cómo sobrescribir el método equals() en clases personalizadas para definir nuestros propios criterios de igualdad de objetos. Esto es crucial para garantizar que nuestros objetos personalizados se comparen en función de su contenido o estado en lugar de solo su ubicación en memoria. Finalmente, aprendimos la importancia de manejar objetos nulos dentro del método equals() para prevenir NullPointerException y garantizar comprobaciones de igualdad robustas.