Sunday, May 10, 2015

Importance of Equals and Hashcode in Apex

Recently while doing code review, I found that all developers should have fundamental understanding of "Why we should implement always Equals and Hashcode in Apex?"

In this post, I am going to share my knowledge with few examples to understand the importance of Equals and Hashcode in Apex.

Apex provides you an option to define an equal method in your custom types. This Equals method along with Hashcode is must when you are going to use your custom types in Sets and as Map keys. I would recommend to make this approach (Implementation of Equals and Hashcode) as best practice. Equality operator (==) is going to use the Equals operator if it is defined.

Why we need this Equals method?
Let me start with one example to show you the problem if Equals method is not implemented. Below is the custom type I am having -

Now below is the test class to compare two instances of MyCustomType. Both the instances of MyCustomType is having myField value set to 10. So my expectation is that when I will compare both the instances, they should return true. Let's see what will happen. Below is the test class.

But unfortunately, below is what you will get -
You see our test class is failing. Do you know the reason? Let me tell you the reason. The reason for this comparison to fail is that I don't have the Equals method in my MyCustomType implemented. If the Equals method is not implemented, then exact equality operator (===) will be used. As Salesforce's documentation states -

Exact Equality Operator (===)  always checks the exact same memory location. So if X and Y reference the exact the same memory location, then Exact Equality Operator (===) will return true, otherwise false.

But in the above case, I don't have Equals method implemented in my MyCustomType. So it will go for exact equality operator (===), but myCustomType1 and myCustomType2 are not referencing the same memory location. So the expression (myCustomType1 == myCustomType2) returns false.
Solution to the above problem -
Let me implement the Equals method in  and execute the same test method. Let's see what will happen then.

After implementing Equals method, the test will pass. Great.
Now I will explain Equals method in details. If you are coming from Java background, it is little different. So it makes sense to understand the concept well.
Deep Dive into Equals Method -
The method signature is: public Boolean equals(Object o). Very easy right!!!. But as a developer, you need to be aware of something. You can't write equals method like public Boolean equals(MyCustomType o). The reasons are -
  • The above implementation will not overwrite Object implementation and will not work with arguments other than of type MyCustomType 
  • The == operator will not use the equals(MyCustomType o) implementation.
Another point to notice at line# 5 (this === o). Here I have used exact equality operator (===) instead of == operator. The reason is if I have used == operator, then that operator will use the Equals method again. So it will become a recursive call and very soon we will hit by stack overflow.

There is another point to remember. As per the specification, the equals method should return null if null is passed. This is getting checked @ line# 8. But the point to make here is that "null instanceof anything will return false" this is available from API version 32.0 and above.
Before API 32.0, it is not available. So there you need to modify your line#8 like below -
if( ( o == null ) || !(o instanceof MyCustomType))
Great, but why we need this Hashcode then?
Apex documentation states that "If two objects are equal, based on the equals method, hashCode must return the same value".
So you should implement Hashcode also.

There is a good documentation on Salesforce. Here is the link . CLICK HERE.
I recommend everyone to read Effective Java by Joshua Bloch.

0 comments:

Post a Comment