Search code examples
javasonarqube

How to get .equals() being symmetric when using .compareTo() in Java


There's a similar question here (Implementing equals method using compareTo) - which in the end recommends to reuse .compareTo() to implement .equals() as long as the contracts aren't violated - my focus here is on the contract x.equals(y) == y.equals(x). A simple implementation of .equals() would/could be

public boolean equals(Object obj) {
  return obj != null && (obj instanceof MyClass) && 0 == this.compareTo((MyClass)obj);
}

So here's my problem: When I have a ParentClass implementing it this way, and a ChildClass which extends ParentClass, I will have the problem that an instance of ChildClass is also an instance of ParentClass, but not vice versa.

So for an instance parent of ParentClass and an instance child of ChildClass it's at least possible - using the above .equals() - that child.equals(parent) != parent.equals(child).

So how to implement .equals() using .compareTo() and guarantee child.equals(parent) == parent.equals(child)?

Any ideas? Thanks.

edit: the origin of this question is SonarQube which complains about the simple implementation not being symmetric - the above question is my interpretation of SonarQube's complaining. The solution should be symmetric but shouldn't involve too much changes.


Solution

  • So, here's a solution that SonarQube (rule findbugs:EQ_UNUSUAL) is happy with ...

    public boolean equals(Object obj)
    {
        return obj != null && this.getClass().equals(obj.getClass()) && this.compareTo(obj) == 0;
    }
    

    At least this seems to be compact and should satisfy the contracts.