Implementing equals method using compareTo

2019-01-25 07:00发布

General question: When implementing an override of the default equals method in Java, what concerns should I have about simply utilizing an already implemented compareTo method vs writing independent logic into the equals method? I noticed someone mention in another question that foo.equals((String)null) returns false whereas String.compareTo((String)null) throws a NullPointerException. What makes these inconsistent results ideal functionality?

Sample equals method:

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

Edit: Quote from documentation on Comparable

The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C. Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false

Edit:

After further review, I find it of note that the Comparable documentation also states the following:

The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)

Ergo, since null.compareTo(x) obviously throws a NPE, x.compareTo(null) should throw a NPE as well. Whereas for equals, that is not necessarily the case. I am pretty big on the proper handling of NPEs, so I find this relatively significant.

2条回答
走好不送
2楼-- · 2019-01-25 07:39

compareTo may involve a lot more work than is necessary just to get an equality answer, which may end up being a performance issue, depending on your application usage.

Other than that, following DRY principles it would be a good idea to re-use the code as you have suggested.

查看更多
贼婆χ
3楼-- · 2019-01-25 07:47

The difference between equals() and compareTo() is that equals() just checks if two objects are equal to each other where the compareTo() is used to identify the natural order of the instances of specified class. Also equals() method has a contract with hashCode() method but compareTo() hasn't.

According to JavaDoc:

Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.

It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is "Note: this class has a natural ordering that is inconsistent with equals."

You can feel free to reuse compareTo() method logic in your equals() method but keep in mind all the contracts to the equals(), hashCode() and contract from JavaDoc for compareTo() method. If they do not conflict with each other then go ahead.

I think that the enforcement of contracts is more important point.

查看更多
登录 后发表回答