Я столкнулся с проблемой, вызванной Java java.awt.geom.Area#equals(Area). Проблема может быть упрощена до следующих 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
}
После некоторой царапины и отладки головы я наконец увидел в источнике JDK, что подпись метода equals в Area выглядит следующим образом:
public boolean equals(Area other)
Обратите внимание, что это не @Override обычный equals метод из Object, а вместо этого просто перегружает метод более конкретным типом. Таким образом, два вызова в приведенном выше примере заканчиваются вызовом различных реализаций equals.
Поскольку это поведение присутствует с Java 1.2, я предполагаю, что это не считается ошибкой. Поэтому я больше заинтересован в том, чтобы выяснить, почему было принято решение не правильно переопределять метод equals, но в то же время обеспечить перегруженный вариант. (Еще один намек на то, что это было фактически принято, - отсутствие перезаписанного метода hashCode().)
Мое единственное предположение заключалось в том, что авторы опасались, что медленная реализация equals для областей непригодна для сравнения равенства при размещении Area в Set, Map и т.д. datastructures. (В приведенном выше примере вы могли бы добавить a в HashSet, и хотя b равен a, вызов contains(b) завершится с ошибкой.) И опять же, почему они не просто назвали сомнительный метод таким образом, чтобы он не сталкивался с таким фундаментальным понятием, как метод equals?