equals Method in Java

We cannot use the logical equality operator, ==, for testing whether two objects are equal since the == operator tests if the two objects are stored in the same memory location. The equals method in the Object class is used to test if the contents of two objects are equal.
As an example, let's look at String objects.
Consider the following code fragment:

String s1 = ''abc";
String s2 = new String("abc");
System.out.println(s1 == "abc");
System.out.println(s2 == "abc");


Because of String sharing, the first println is likely to output true; however, the second statement will output false. The String class overrides the equals method to return a value of true if the contents of two Strings are equal. So if we replace the println statements with

System.out.println(s1.equals("abc")); System.out.println(s2.equals("abc"));

Then true will be output in both cases.

What if we have created our own objects and want to test for equality? For example, suppose we have created the following Employee class:

Employee
class Employee
{
int empNumber;
String name;
int salary;

public Employee(int empNumber, String name, int salary)
{
this.empNumber = empNumber;
this.name = name;
this.salary = salary;
}
}


We create Employee objects, e1 and e2, as follows:

Employeee1 = new Employee(1, ''Sim", 15000); Employeee2 = new Employee(1, "Sim", 15000);

We want to test if the contents of e1 and e2 are the same. We cannot use the Object.equals method because its default behavior is to act like the == operator. We need to override the equal’s method so that it acts much like the overridden String.equals method. The Java Language Specification1 states that an overridden equals method must exhibit the following properties:


It is reflexive. For any reference value x, x.equals(x) should return true.

It is symmetric. For any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

It is transitive. For any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.

It is consistent. For any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparison on the object is modified.

For any nonnull reference value x, x.equals(null) should return false.

The preceding properties define an equivalence relation. The listing shows an overridden equals method that we might add to the Employee class.

equals Method
public boolean equals(Object o)
{
if (o == this)
{
return true;
}

if (o == null)
{
return false;
}
if (getClass() != o.getClass() )
{
return false;
}
Employee e = (Employee) o;
return empNumber == e.empNumber
&& name.equals(e.name)
&& salary == e.salary;
}



Lines 2–4 are a check if the argument, o, is a reference to this object. If so, return true. This statement is for efficiency only; it saves the later checking (as in lines 12–14) of the individual fields that could be computationally expensive. In lines 5–7, a null argument fails the equality test in line with the last requirement of the preceding equals equivalence relation. In lines 8–10, we test whether this object and the argument belong to the same class. We use the Object.getClass method, which returns the runtime class of an object. If the two objects do not belong to the same class, they cannot be equal. In line 11,we cast the object argument to an Employee type. Finally, in lines 12–14, we test if the fields of the two objects have identical values. For primitive types, such as the intempNumber and salary, we can safely use the == operator. For the String name,
we use the overridden String.equals method.

No comments:

Post a Comment