Wednesday, November 7, 2012

Why @Override annotation is important in Java?

The 'Override' annotation was introduced with Java 1.5 release which indicates that the annotated method declaration overrides the declaration in a super class. This annotation is used highly and most of the modern IDE's added this annotation automatically when we use some IDE's features. If you consistently use this annotation, it will protect you from a large class of sever bugs. Let's have some example. Consider the following class declaration.

public class Employee {

    private String nicNo;
    private String name;
 
    public Employee(String nicNo, String name) {
         super();
         this.nicNo = nicNo;
         this.name = name;
    }
    public String getNicNo() {
         return nicNo;
    }
    public void setNicNo(String nicNo) {
         this.nicNo = nicNo;
    }
    public String getName() {
         return name;
    }
    public void setName(String name) {
         this.name = name;
    }
    public int hashCode() {
         final int prime = 31;
         int result = 1;
         result = prime * result + ((nicNo == null) ? 0 : nicNo.hashCode());
         return result;
    }
    public boolean equals(Employee obj) {
         return obj.nicNo == this.nicNo;
    }
}



We have not forgotten to implement both equals() and hashCode() method and used same field for both method which is a good practice. See carefully the equals() method implementation. According to that, if two Employee instances have same 'nicNo' those should be equal. Let's have a look on following example code.

public class OverrideTest {

    public static void main(String args[]) {
  
        Employee emp1 = new Employee("800410452v", "Brayan");
        Employee emp2 = new Employee("800410451v", "Nick");
        Employee emp3 = new Employee("800410453v", "Jhon");
        Employee emp4 = new Employee("800410453v", "Wiki");
  
        Set<Employee> empSet = new HashSet<Employee>();
        empSet.add(emp1);
        empSet.add(emp2);
        empSet.add(emp3);
        empSet.add(emp4);
        System.out.println(empSet.size());  
    }
}

We are going to insert four Employee instances into the Set. Set can not have duplicates. 

What will be the output of above program?

You may expect '3' as the output, since 'emp3' and 'emp4' both instance have same 'nicNo' and according to the equals() method, those two should be equal. So 'empSet' can not have both instances. 

But the above code will result '4' as the output.

Where we went wrong?

It must be the equals() method of Employee class. We intended to override equals() method and even hashCode() method. To override Object.equals, we must define an equals method whose parameter is of type Object, but the parameter of Employee’s equals method is not of type Object. 

So Employee inherits the equals() method from Object class which tests the object identity, just like == operator does. Therefor, both 'emp3' and 'emp4' will be stored in Set collection. The compiler can indicates this kind of wrong implementation in advance, only if you have helped to compiler saying that you are going to override Object's equals() method. To do this, you have to annotate the method with Override annotation as follows.

 @Override
 public boolean equals(Employee obj) {
      return obj.nicNo == this.nicNo;
 }

The above code will give you a compilation error.

Your IDE will generate equals(), hashCode() and toString() methods which satisfy all the requirements. See the bellow equals() method which eclipse created for me which is very smart.

 @Override
 public boolean equals(Object obj) {
     if (this == obj)
         return true;
     if (obj == null)
         return false;
     if (getClass() != obj.getClass())
         return false;
     Employee other = (Employee) obj;
     if (nicNo == null) {
         if (other.nicNo != null)
             return false;
     } else if (!nicNo.equals(other.nicNo))
             return false;
     return true;
 }

Therefore, it is a very good practice using Override annotation when you intend to override super class method declaration. Most of the IDE's gives warning with the methods which does not annotated with Override, but overrides the super class method correctly. The compiler can protect you from a great many errors if you use the Override annotation on every method declaration that you believe to override a supertype declaration.

4 comments:

  1. One of the many features that are already in C# for a long time that needed to be in Java!

    ReplyDelete
  2. In text , instead of equal() should be equals()

    ReplyDelete

Share

Widgets