I just ran into a problem caused by Java's java.awt.geom.Area#equals(Area)
method. The problem can be simplified to the following unit test:
@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
}
After some head scratching and debugging, I finally saw in the JDK source, that the signature of the equals
method in Area
looks like this:
public boolean equals(Area other)
Note that it does not @Override
the normal equals
method from Object
, but instead just overloads the method with a more concrete type. Thus, the two calls in the example above end up calling different implementations of equals
.
As this behavior has been present since Java 1.2, I assume it is not considered a bug. I am, therefore, more interested in finding out why the decision was made to not properly override the equals
method, but at the same time provide an overloaded variant. (Another hint that this was an actual decision made is the absence of an overwritten hashCode()
method.)
My only guess would be that the authors feared that the slow equals
implementation for areas is unsuitable for comparing equality when placing Area
s in Set
,Map
,etc. datastructures. (In the above example, you could add a
to a HashSet
, and although b
is equal to a
, calling contains(b)
will fail.) Then again, why did they not just name the questionable method in a way that does not clash with such a fundamental concept as the equals
method ?
"Why does Java's Area#equals method not override Object#equals?"
Because overriding is not necessary for overloaded methods where the parameters are of differing types.
This case does not compel us to override but it is overloading as it follows these rules:
"why did they not just name the questionable method in a way that does not clash with such a fundamental concept as the equals method?"
Because this could trip people up going into the future. If we had a time machine to the 90's we could do it without this concern.
RealSkeptic linked to JDK-4391558 in a comment above. The comment in that bug explains the reasoning:
but:
So basically we're left with an array of not-so-pleasant options, such as:
or:
or:
or other ways to modify the
equals(Area)
behavior that would either change its semantics or make it inconsistent withhashCode
.Looks like changing this method is deemed by the maintainers to be neither feasible (because neither option outlined in the bug comment quite solves the problem) nor important (since the method, as implemented, is quite slow and would probably only ever return true when comparing an instance of an
Area
with itself, as the commenter suggests).