Thou Shalt Not Name Thy Method “Equals”
(unless you really override Object.equals()
, of course).
I’ve stumbled upon a rather curious Stack Overflow question by user Frank:
Why does Java’s Area#equals method not override Object#equals?
Interestingly, there is a Area.equals(Area)
method which really takes an Area
argument, instead of a Object
argument as declared in Object.equals()
. This leads to rather nasty behaviour, as discovered by Frank:
@org.junit.Test public void testEquals() { java.awt.geom.Area a = new java.awt.geom.Area(); java.awt.geom.Area b = new java.awt.geom.Area(); assertTrue(a.equals(b)); // -> true java.lang.Object o = b; assertTrue(a.equals(o)); // -> false }
Technically, it is correct for AWT’s Area to have been implemented this way (as hashCode()
isn’t implemented either), but the way Java resolves methods, and the way programmers digest code that has been written like the above code, it is really a terrible idea to overload the equals method.
No static equals, either
These rules also hold true for static equals()
methods, such as for instance Apache Commons Lang‘s
ObjectUtils.equals(Object o1, Object o2)
The confusion here arises by the fact that you cannot static-import this equals method:
import static org.apache.commons.lang.ObjectUtils.equals;
When you now type the following:
equals(obj1, obj2);
You will get a compiler error:
The method equals(Object) in the type Object is not applicable for the arguments (…, …)
The reason for this is that methods that are in the scope of the current class and its super types will always shadow anything that you import this way. The following doesn’t work either:
import static org.apache.commons.lang.ObjectUtils.defaultIfNull; public class Test { void test() { defaultIfNull(null, null); // ^^ compilation error here } void defaultIfNull() { } }
Details in this Stack Overflow question.
Conclusion
The conclusion is simple. never overload any of the methods declared in Object
(overriding is fine, of course). This includes:
clone()
equals()
finalize()
getClass()
hashCode()
notify()
notifyAll()
toString()
wait()
Of course, it would be great if those methods weren’t declared in Object
in the first place, but that ship has sailed 20 years ago.
Reference: | Thou Shalt Not Name Thy Method “Equals” from our JCG partner Lukas Eder at the JAVA, SQL, AND JOOQ blog. |