`
iloveflower
  • 浏览: 76766 次
社区版块
存档分类
最新评论
  • iloveflower: 呵呵。好好学习。。。。。。。。。。。。
    java 读书
  • Eric.Yan: 看了一点,不过是电子版的……你这一说到提醒我了,还要继续学习哈 ...
    java 读书

How to override equals method in Java

 
阅读更多
Object class holds some very interesting method which is applicable at object level and one of them is equals () which we are going to discuss in this article. equals () method is used to compare the equality of two object. default implementation of equals() class provided by Object class compares memory location and only return true if two reference variable are pointing to same memory location i.e. essentially they are same object. JAVA recommends to override equals method if equality is going to be define by logical way or via some business logic and some classes in Java standard library does override it e.g. String class whose implementation of equals() method return true if content of two strings are exactly same.
java has provided a contract to follow while overriding equals () method which state that as per Java your equals()  method should adhere following rule:




1) Reflexive: Object must be equal to itself.

2) Symmetric: if a.equals(b) is true then b.equals(a) must be true.

3) Transitive: if a.equals(b) is true and b.equals(c) is true then c.equals(ad) must be true.

4) Consistent: multiple invocation of equals() method must result same value until any of properties are modified. So if two objects are equals in Java they will remain equals until any of there property is modified.

5) Null comparison: comparing any object to null must be false and should not result in NullPointerException. For example a.equals(null) must be false.




And equals method in Java must follow its commitment with hashcode as stated below.




1) If two objects are equal by equals() method then there hashcode must be same.

2) If two objects are unequal by equals() method then there hashcode could be same or different.




So this was the basic theory about equals () method in Java now we are going to discuss the approach on how to override equals () method, yes I know you all know this stuff but I have seen some of equals () code which can really be improved by following correct. For illustration purpose we will see an example of Person class and discuss How to write equals () method for that class.

Overriding equals method in Java

Here is my approach for overriding equals () method in Java. This is based on standard approach most of java programmer follows while writing equals method in Java.




1) Do this check -- if yes then return true.

2) Do null check -- if yes then return false.
3) Do the instanceof check if instanceof return false than return false , after some research I found that instead of instanceof we can use getClass() method for type identification because instanceof check returns true for subclass also, so its not strictly equals comparison until required by business logic. But instanceof check is fine if your class is immutable and no one is going to sub class it. For example we can replace instanceof check by below code
if((obj == null) || (obj.getClass() != this.getClass()))
        return false;




4) Type cast the object; note the sequence instanceof check must be prior to casting object.

5) Compare individual attribute start with numeric attribute because comparing numeric attribute is fast and use short circuit operator for combining checks.  So if first field does not match, don't try to match rest of attribute and return false. It’s also worth to remember doing null check on individual attribute before calling equals() method on them recursively to avoid NullPointerException during equals check in Java.




Code Example of overriding equals method in Java

Let’s see a code example based on my approach of overriding equals method in Java as discussed in above paragraph:
class Person{            private int id;            private String firstName;            private String lastName;                        public int getId() {                        return id;            }                        public void setId(int id) {                        this.id = id;            }                        public String getFirstName() {                        return firstName;            }

        public void setFirstName(String firstName) {                        this.firstName = firstName;            }                        public String getLastName() {                        return lastName;            }                        public void setLastName(String lastName) {                        this.lastName = lastName;            }

        public boolean equals(Object obj){
         if(obj == this){
             return true;
         }
         if(obj == null || obj.getClass() != this.getClass()){
             return false
         }
       
         Person guest = (Person) obj;   
         return id == guest.id &&
                (firstName == guest.firstName || (firstName != null && firstName.equals(guest.getFirstName()) &&
                (lastName  == guest.lastName  ||  (lastName != null && lastName.equals(guest.getLastName());
        }          
If you look above method we are first checking for "this" check which is fastest available check for equals method then we are verifying  whether object is null or not and object is of same type or not. only after verifying type of object we are casting it into desired object to  avoid any ClassCastException in Java. Also while comparing individual attribute we are comparing numeric attribute first ,using short circuit operator to avoid further calculation if its already unequal and doing null check on member attribute to avoid NullPointerException.

           

           

Common Errors while overriding equals in Java

Though equals and hashcode method are defined in Object class and one of fundamental part of Java programming I have seen many programmers making mistake while writing equals() method in Java. I recommend all Java programmer who has just started programming to write couple of equals and hashcode method for there domain or value object to get feel of it. Here I am listing some of common mistakes I have observed on various equals method in Java.



1) Instead of overriding equals() method programmer overloaded it.
This is the most common error I have seen while overriding equals method in Java. Syntax of equals method defined in Object class is public boolean equals(Object obj) but many people unintentionally overload equals method in Java by writing public boolean equals(Person obj), instead of using Object as argument they use there class name. This error is very hard to detect because of static binding. So if you call this method in your class object it will not only compile but also execute correctly but if you try to put your object in collection e.g. ArrayList and call contains() method which is based on equals() method in Java it will not able to detect your object. So beware of it.


2) Second mistake I have seen while overriding equals() method is not doing null check for member variables which ultimately results in NullPointerException during equals() invocation. For example in above code correct way of calling equals() method of member variable is after doing null check as shown below:

firstname == guest.firstname || (firstname != null && firstname.equals(guest.firstname)));


3) Third mistake I have seen is not overriding hashcode method in Java and only overriding equals() method. You must have to override both equals() and hashcode() method in Java , otherwise your value object will not be able to use as key object in HashMap because hashmap in based on equals() and hashcode to read more see , How HashMap works in Java
 
Writing JUnit tests for equals method in Java
Its good practice to write JUnit test cases to test your equals method. Here is my approach for writing JUnit test case for equals method in Java. I will write test cases to check equals behavior on different circumstances:

·          testReflexive() this method will test reflexive nature of equals() method in Java.

·          testSymmeteric() this method will verify symmetric nature of equals() method in Java.

·          testNull() this method will verify null comparison and will pass if equals method returns false.

·          testConsistent() will verify consistent nature of equals method in Java.

·          testNotEquals() will verify if two object which are not supposed to equals is actually not equal

·          testHashcode() will verify that if two objects are equal by equals() method in Java then there hashcode must be same.




5 Tips on Equals method in Java




Tip: most of the IDE provides support to generate equals() and hashcode() method

In Eclipse do the right click-> source -> generate hashCode() and equals().

Tip: if your domain class has any unique business key then just comparing that field in equals method would be enough instead of comparing all the fields e.g. in case of our example if "id" is unique for every person then by just comparing id we will be able to identify whether two persons are equal or not.

Tip: while overriding hashcode method in Java makes sure you use all fields which have been used while writing equals method in Java.

Tip: String and Wrapper classes in java override equals method but StringBuffer doesn’t override it.

Tip: Whenever possible try to make your fields immutable, equals method based on immutable fields are much secure than equals method based on mutable fields.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics