6

We have few datatypes defined for our service response and request objects in a model. Recently we found a need of implementing ToString, HashCode and Equals on all such types to make use of these over comparison and assertions. Confirming from few source like What issues should be considered when overriding equals and hashCode in Java?, Right way to implement equals contract etc we followed implementing toString, equals and hashcode using org.apache.commons.lang3.builder.EqualsBuilder, HashCodeBuilder and ToStringBuilder as follows -


Response.java

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

public class Response {

    private Integer value;
    private Currency currency;
    private Object edited;

    public Response() {
    }

    public Response(Integer value, Currency currency, Object edited) {
        this.value = value;
        this.currency = currency;
        this.edited = edited;
    }

    public Currency getCurrency() {
        return currency;
    }

    public void setCurrency(Currency currency) {
        this.currency = currency;
    }

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public Object getEdited() {
        return edited;
    }

    public void setEdited(Object edited) {
        this.edited = edited;
    }

    @Override public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Response Response = (Response) o;
        return new EqualsBuilder().append(value, Response.value).append(currency, Response.currency)
                                  .append(edited, Response.edited).isEquals();
    }

    @Override public int hashCode() {
        return new HashCodeBuilder(17, 37).append(value).append(currency).append(edited).toHashCode();
    }

    @Override public String toString() {
        return "Response{" + "value=" + value + ", currency=" + currency + ", edited=" + edited + '}';
    }
}

Currency.java

public enum Currency {
    INR
}

On implementing these using the default library version, there is a thought around enums that comes to our mind -

Is it correct to use the default hashcode and equals from the library when a datatype might contain parameters including enums as well? Is there a library(within commons would be great) support to implementing a correct optimized solution to overriding implementation of hashcode and equals?

On a side note does the library implementation needs an improvement here or is it correct to what exists?


Edit: Have added the implementation over an Object field(edited) in the class as well. The concern there being same if I override the hashCode and equals implementation for these as well.

Do I end up using an Object's hashcode which is different for different instances as it is mostly the memory mapped address?

Edit 2: I can also see a concern raised on the inconsistent implementation on HashCode for Enum values on JIRA

Community
  • 1
  • 1
Naman
  • 27,789
  • 26
  • 218
  • 353
  • 3
    Enums have a default, perfectly correct implementation of hashCode and equals. – Louis Wasserman Oct 14 '16 at 00:56
  • @LouisWasserman does that mean I can rely on the current implementation? any thoughts over comparing two objects of `Response` type generated using different JVMs? – Naman Oct 14 '16 at 04:19
  • A) yes B) you can only call `equals` from inside a single JVM. – Louis Wasserman Oct 14 '16 at 05:34
  • @LouisWasserman Thank you. Can you provide any source for in-depth understanding of `B` above. – Naman Oct 14 '16 at 05:42
  • You are calling .equals. .equals is being called in one Java runtime. That's the one. – Louis Wasserman Oct 14 '16 at 06:19
  • @LouisWasserman - got your point, apologies but have updated the question with a concern over Object fields here as well. – Naman Oct 14 '16 at 07:23
  • @nullpointer. I think that is a non issue. See the resolution notes they have marked it as "Won't Fix ". This JIRA was opened in Dec 2011 and close recently in Oct 2016. I do not think this will be an issue as well. It seems they had added a patch in 2014, so logically speaking this shouldnt be a concern. – Acewin Nov 11 '16 at 17:17
  • Reading it further I noticed this was not opened as bug a a new feature. Hence using HashCodeBuilder the way you are using should be fine – Acewin Nov 11 '16 at 17:22
  • @Acewin The use case we are aware of is as and when generation of different hashCode values for enum arises when a serialisation and deserialisation of response objects occurs on two different machines. – Naman Nov 12 '16 at 04:43
  • 1
    @nullpointer you shouldn't have any code dependent on the value of the hashcode (i.e. don't include that in your serialization), other than in building a hashcode encompassing contained objects. The only requirement you can and should depend on is that the value remains consistent within an instance of the JVM runtime. – Richard Sitze Nov 13 '16 at 22:22
  • Which is not the case in the code example. You should only use fields in hashcode/equals that are effectively final. If you use your object as a key in a HashMap, and change the fields, the object may no longer hash to the same bucket. – NickL Apr 11 '17 at 21:01

0 Answers0