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.
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.
Open the WebIDE and make sure you are in the
~/projectdirectory. You can confirm this by looking at the terminal prompt or by typingpwdand pressing Enter.Create a new file named
EqualityDemo.javain the~/projectdirectory. You can do this by right-clicking in the File Explorer on the left and selecting "New File", then typingEqualityDemo.java.Open the
EqualityDemo.javafile 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
Stringobjects,str1andstr2, with the same content ("hello") but usingnew String(), which creates distinct objects in memory. - We create a third
Stringreference,str3, and make it point to the same object asstr1. - We use both
==andequals()to comparestr1andstr2, andstr1andstr3. - We also show a comparison of primitive
inttypes using==. Remember thatequals()is used for objects, not primitive types.
- We create two
Save the
EqualityDemo.javafile (Ctrl+S or Cmd+S).Open the Terminal at the bottom of the WebIDE.
Compile the Java program by typing the following command and pressing Enter:
javac EqualityDemo.javaIf there are no errors, you should see no output.
Run the compiled program by typing the following command and pressing Enter:
java EqualityDemoYou 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: trueNotice that
str1 == str2isfalsebecause they are different objects in memory, even though they have the same content. However,str1.equals(str2)istruebecause theStringclass'sequals()method is overridden to compare the actual content of the strings.str1 == str3istruebecausestr3points to the exact same object asstr1.
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.
Make sure you are in the
~/projectdirectory in the WebIDE.Create a new file named
Person.javain the~/projectdirectory.Open
Person.javaand paste the following code for thePersonclass: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
Personclass:- We have two private attributes:
name(String) andage(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 overriddenequals():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 thePersonclass. If either is true, they cannot be equal.Person person = (Person) obj;: We cast the genericObjectto aPersonobject so we can access itsnameandageattributes.return age == person.age && name.equals(person.name);: This is the core of the logical comparison. We check if theageis the same (using==for primitive int) and if thenameis the same (usingequals()for String objects).
- We have two private attributes:
Save the
Person.javafile.Now, let's create another file,
PersonEqualityDemo.java, to test our overriddenequals()method. Create this file in the~/projectdirectory.Open
PersonEqualityDemo.javaand 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
Personobjects and compare them using both==and our overriddenequals()method.Save the
PersonEqualityDemo.javafile.Open the Terminal. Make sure you are in
~/project.Compile both Java files. You can compile multiple files at once:
javac Person.java PersonEqualityDemo.javaThis should create
Person.classandPersonEqualityDemo.classfiles.Run the demo program:
java PersonEqualityDemoYou 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): trueAs expected,
person1 == person2isfalsebecause they are distinct objects, butperson1.equals(person2)istruebecause theirnameandageare the same according to our overridden method.person1andperson3are not equal by either comparison.person1andperson4are 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.
Make sure you are in the
~/projectdirectory in the WebIDE.Open the
PersonEqualityDemo.javafile that you created in the previous step.Add the following lines to the
mainmethod, 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
person1withnull.Save the
PersonEqualityDemo.javafile.Open the Terminal. Make sure you are in
~/project.Compile the modified
PersonEqualityDemo.javafile:javac PersonEqualityDemo.javaRemember that you only need to recompile the files you have changed. Since
Person.javawas not changed in this step, we only need to compilePersonEqualityDemo.java.Run the compiled program:
java PersonEqualityDemoYou 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): falseThe output
person1.equals(null): falseconfirms that our overriddenequals()method correctly handles the comparison withnulland returnsfalsewithout throwing aNullPointerException. This is because the lineif (obj == null || getClass() != obj.getClass())in ourPersonclass'sequals()method checks fornullbefore attempting to access any attributes ofobj.
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.



