As a best practice in Java, POJO classes or Data objects always declare the fields private and expose their access through the getter methods. On rare occasions, we may encounter situations when the member fields are private, and the class does not provide the public accessor methods. For example, the class may have been generated from a tool.
In such cases, when we do not have access to the source code and cannot add the equals() method in the Java class file, we can take advantage of the EqualsBuilder class to build a good equals method for any class outside that class.
1. EqualsBuilder.reflectionEquals() Method
The reflectionEquals(), as the name suggests, uses reflection (AccessibleObject.setAccessible method) to change the visibility of the private fields in the generated class. Then it will iterate over all the fields (if not explicitly excluded from comparison) and compare their values.
- The primitives are compared for their value.
- The non-primitives are compared using their equals() method.
- Transient members are not tested, as they are likely derived fields, and not part of the value of the Object.
- Static fields are not tested.
- Superclass fields are also tested for equality.
We can add the Apache Common Lang library by including the ‘org.apache.commons:commons-lang3‘ dependency.
A typical invocation for reflectionEquals() method would look like:
To exclude certain fields from the comparison, we can pass a list of field names as the third parameter in the method.
2. Demo
Let’s suppose we have a Java class Person that was generated using a third-party library and does not contain the public getter method.
We can compare two instances of the Person class for equality as follows:
3. Excluding Fields from Equality Comparison
Suppose we do not want to compare the field “id” duing the equals comparison and only want to compare the fields: name, email and phone. In such case, we can pass the “id” field name as a List in the reflectionEquals() method argument.
4. Handling Inheritance
What if the value object, we are comparing, is part of a nested class hirarchy and we do not want to compare the fields in the super class for any reason. This is also possible by setting the reflectUpToClass method argument.
Take an example of following hierarchy:
When compating objects for equality, we only want to compare the fields in ChildVo. The fields in BaseVo should not be compared.
In the following example, the id field belongs to BaseVo and its value will not be used in equals() comparison.
5. Summary
As discussed in Start, this is very highly unlikely to encounter situations where a class have only private fields and no public accessor method. But, when we encounter such situation and want to perform an equality check then EqualsBuilder.setReflectUpToClass is an excellent choice.
Happy Learning !!
Reference: EqualsBuilder Class Java Doc
Comments