How to Check If Two Objects Are Equal in Java

JavaJavaBeginner
Practice Now

Introduction

In this lab, you will learn how to check if two objects are equal in Java. We will explore the fundamental difference between using the == operator and the equals() method for object comparison.

You will start by using the built-in equals() method to compare objects and understand its behavior with different data types. Then, you will learn how to override the equals() method in your own custom classes to define what constitutes logical equality for your objects. Finally, you will address the important consideration of handling null objects when performing equality checks to prevent potential NullPointerException errors.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java(("Java")) -.-> java/StringManipulationGroup(["String Manipulation"]) java(("Java")) -.-> java/ProgrammingTechniquesGroup(["Programming Techniques"]) 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{{"How to Check If Two Objects Are Equal in Java"}} java/method_overriding -.-> lab-560013{{"How to Check If Two Objects Are Equal in Java"}} java/classes_objects -.-> lab-560013{{"How to Check If Two Objects Are Equal in Java"}} java/object_methods -.-> lab-560013{{"How to Check If Two Objects Are Equal in Java"}} end

Use equals() Method for Equality

In this step, we will explore how to compare objects in Java using the equals() method. While the == operator checks if two object references point to the exact same object in memory, the equals() method is designed to check if two objects are logically equal, meaning they represent the same value or state.

Let's start by creating a simple Java file to demonstrate this concept.

  1. Open the WebIDE and make sure you are in the ~/project directory. You can confirm this by looking at the terminal prompt or by typing pwd and pressing Enter.

  2. Create a new file named EqualityDemo.java in the ~/project directory. You can do this by right-clicking in the File Explorer on the left and selecting "New File", then typing EqualityDemo.java.

  3. Open the EqualityDemo.java file in the editor and paste the following code:

    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));
        }
    }

    In this code:

    • We create two String objects, str1 and str2, with the same content ("hello") but using new String(), which creates distinct objects in memory.
    • We create a third String reference, str3, and make it point to the same object as str1.
    • We use both == and equals() to compare str1 and str2, and str1 and str3.
    • We also show a comparison of primitive int types using ==. Remember that equals() is used for objects, not primitive types.
  4. Save the EqualityDemo.java file (Ctrl+S or Cmd+S).

  5. Open the Terminal at the bottom of the WebIDE.

  6. Compile the Java program by typing the following command and pressing Enter:

    javac EqualityDemo.java

    If there are no errors, you should see no output.

  7. Run the compiled program by typing the following command and pressing Enter:

    java EqualityDemo

    You should see output similar to this:

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

    Notice that str1 == str2 is false because they are different objects in memory, even though they have the same content. However, str1.equals(str2) is true because the String class's equals() method is overridden to compare the actual content of the strings. str1 == str3 is true because str3 points to the exact same object as str1.

This demonstrates the key difference between == (reference equality) and equals() (logical equality) when comparing objects in Java. For primitive types, == is used for value comparison.

Override equals() in Custom Class

In the previous step, we saw how the equals() method works for String objects. The String class has already overridden the default equals() method (inherited from the Object class) to provide meaningful comparison based on content.

However, when you create your own custom classes, the default equals() method inherited from Object simply uses the == operator, meaning it only checks for reference equality. To compare objects of your custom class based on their attributes (logical equality), you need to override the equals() method yourself.

In this step, we will create a simple Person class and override its equals() method.

  1. Make sure you are in the ~/project directory in the WebIDE.

  2. Create a new file named Person.java in the ~/project directory.

  3. Open Person.java and paste the following code for the Person class:

    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
        }
    }

    In this Person class:

    • We have two private attributes: name (String) and age (int).
    • We have a constructor to initialize these attributes.
    • We have getter methods to access the attributes.
    • We have overridden the equals() method. Let's look at the steps inside the overridden equals():
      • if (this == obj): This is an optimization. If the two references point to the exact same object, they are definitely equal.
      • if (obj == null || getClass() != obj.getClass()): This checks if the object being compared to is null or if it's not an instance of the Person class. If either is true, they cannot be equal.
      • Person person = (Person) obj;: We cast the generic Object to a Person object so we can access its name and age attributes.
      • return age == person.age && name.equals(person.name);: This is the core of the logical comparison. We check if the age is the same (using == for primitive int) and if the name is the same (using equals() for String objects).
  4. Save the Person.java file.

  5. Now, let's create another file, PersonEqualityDemo.java, to test our overridden equals() method. Create this file in the ~/project directory.

  6. Open PersonEqualityDemo.java and paste the following code:

    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));
        }
    }

    In this demo class, we create several Person objects and compare them using both == and our overridden equals() method.

  7. Save the PersonEqualityDemo.java file.

  8. Open the Terminal. Make sure you are in ~/project.

  9. Compile both Java files. You can compile multiple files at once:

    javac Person.java PersonEqualityDemo.java

    This should create Person.class and PersonEqualityDemo.class files.

  10. Run the demo program:

    java PersonEqualityDemo

    You should see output similar to this:

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

    As expected, person1 == person2 is false because they are distinct objects, but person1.equals(person2) is true because their name and age are the same according to our overridden method. person1 and person3 are not equal by either comparison. person1 and person4 are equal by both comparisons because they refer to the same object.

By overriding the equals() method, you define what "equal" means for objects of your custom class based on their logical state rather than just their memory location.

Handle Null Objects in Equality

In the previous step, we successfully overrode the equals() method in our Person class to compare objects based on their attributes. One crucial aspect of writing robust equals() methods is handling potential null values. If you try to call a method on a null object, it will result in a NullPointerException, which is a common error in Java.

Our overridden equals() method in Person.java already includes a check for null: if (obj == null || getClass() != obj.getClass()). This is the standard way to handle the case where the object being compared to is null.

In this step, we will demonstrate what happens when comparing an object to null and confirm that our equals() method handles it correctly.

  1. Make sure you are in the ~/project directory in the WebIDE.

  2. Open the PersonEqualityDemo.java file that you created in the previous step.

  3. Add the following lines to the main method, after the existing comparison statements:

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

    This code simply adds a comparison of person1 with null.

  4. Save the PersonEqualityDemo.java file.

  5. Open the Terminal. Make sure you are in ~/project.

  6. Compile the modified PersonEqualityDemo.java file:

    javac PersonEqualityDemo.java

    Remember that you only need to recompile the files you have changed. Since Person.java was not changed in this step, we only need to compile PersonEqualityDemo.java.

  7. Run the compiled program:

    java PersonEqualityDemo

    You should now see the previous output followed by the new comparison with 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

    The output person1.equals(null): false confirms that our overridden equals() method correctly handles the comparison with null and returns false without throwing a NullPointerException. This is because the line if (obj == null || getClass() != obj.getClass()) in our Person class's equals() method checks for null before attempting to access any attributes of obj.

Handling null is a critical part of writing robust code in Java, especially when dealing with object comparisons. Always include a null check at the beginning of your overridden equals() method.

Summary

In this lab, we learned how to check if two objects are equal in Java. We started by understanding the difference between the == operator, which checks for reference equality, and the equals() method, which checks for logical equality. We demonstrated this using String objects and primitive types, observing how == behaves differently from equals() for objects.

We then explored how to override the equals() method in custom classes to define our own criteria for object equality. This is crucial for ensuring that our custom objects are compared based on their content or state rather than just their memory location. Finally, we learned the importance of handling null objects within the equals() method to prevent NullPointerException and ensure robust equality checks.