Overriding equals() method in java

The main purpose of the equals() method is to check the equality of two objects. Whenever we don’t override the equals() method in our class then the Object class equals() method will be overridden by default.

Internal code of equals() method in Object class
  
  public boolean equals(Object paramObject)
  {
    return this == paramObject;
  }


Object class equals() method is to compare the reference of an object


The problem without overriding equals() method



public class StudentRecord {
       public static void main(String[] args) {
              Student s1=new Student(10,"student1");
              Student s2=new Student(10,"student1");
              Student s3=s1;
              System.out.println(s1.equals(s2)); // false
              System.out.println(s1.equals(s3)); // true
       }
}

class Student{
       int id;
       String name;
       Student(int id,String name){
              this.id=id;
              this.name=name;
       }
}




In the above example, s1.equals(s2) returns false even though the content is the same because here it compares the reference of the object not the content of an object. References s1&s2 are pointing to different objects.
In the case of s1.equals(s3) returns true because here s1&s3 references pointing the same object.

The benefit of overriding equals() method


We compare the content of two objects using object1.equals(object2)
If you look at the equals() method in the below example public boolean equals(Object obj) in this method equals(Object obj) is the second object that we should typecast as shown below.


public class StudentRecord {
       public static void main(String[] args) {
              Student s1=new Student(10,"student1");
              Student s2=new Student(10,"student1");
              Student s3=s1;
              Student s4=new Student(20,"student2");
              System.out.println(s1.equals(s2)); // true
              System.out.println(s1.equals(s3)); // true
              System.out.println(s1.equals(s4)); // false
       }
}

class Student{
       int id;
       String name;
       Student(int id,String name){
              this.id=id;
              this.name=name;
       }
       @Override
       public boolean equals(Object obj) {
             // student-1 id, name
              String name1=this.name;
              int id1=this.id;
              // student-2 id, name
              Student stu2=(Student) obj; // typecast object to student
              String name2=stu2.name;
              int id2=stu2.id;
              if(name1.equals(name2)&&id1==id2){
                     return true;
              }
              else{
                     return false;
              }
       }
}


In the equals() method implementation of if(name1.equals(name2)&&id1==id2)  condition, name1&name2 are comapre with equals() method because name is String and id1&id2 are compare with == operator because id is primitive type.

s1.equals(s2) returns true because the content is the same even though pointing different objects
s1.equals(s3) returns true because the content is the same and pointing the same object
s1.equals(s4) returns false because content is different in both objects.

Note: we are typecasting object to Student [Student stu2=(Student) obj], if the object is not Student type then we will get RuntimeException is ClassCastException
if the Student type is null then we will get RuntimeException is NullPointerException


by using try-catch we have to handle those exceptions


       
       @Override
       public boolean equals(Object obj) {
              try{
                     String name1=this.name;
                     int id1=this.id;
                     Student stu2=(Student) obj;
                     String name2=stu2.name;
                     int id2=stu2.id;
                     if(name1.equals(name2)&&id1==id2){
                           return true;
                     }
                     else{
                           return false;
                     }
              }
              catch(ClassCastException e1){
                     return false;             
              }
              catch(NullPointerException e2){
                     return false;
              }            
       }


Simplified of equals() method


       
       @Override
       public boolean equals(Object obj) {
              try{
                     Student stu2=(Student) obj;
                     if(name.equals(stu2.name)&&id==stu2.id){
                           return true;
                     }
                     else{
                           return false;
                     }
              }
              catch(ClassCastException e1){
                     return false;             
              }
              catch(NullPointerException e2){
                     return false;
              }            
       }


More simplified equals() without try-catch


      
       @Override
       public boolean equals(Object obj) {
              if(obj==this){
                     return true;
              }
              if(obj instanceof Student && obj!=null){
                     Student stu2=(Student) obj;
                     if(name.equals(stu2.name)&&id==stu2.id){
                           return true;
                     }
                     else{
                           return false;
                     }                   
              }
              return false;
       }


In this case, if(obj instanceof Student && obj!=null) line will check, If the student is the object type or not and null or not.
If the student is null or not object type then returns false

It is optional but for better performens:


             if(obj==this){
                     return true;
              }

Whenever we have to check the equality of 10,000 records, in this case, 2000 references point to the same record.

In this case, do we need to check id&name for 2000 records? no need
Because s1 to s2000 point to the same object so content is also the same then we check using the == operator.

if(obj==this){ return true; }

If we don’t use the above the line of the code then should be the check that 2000 records with remaining all the records of equality at this line if(name.equals(stu2.name)&&id==stu2.id) and it will take more time.



No comments:

Post a Comment