(конечно, если вы не переопределите Object.equals()
).
Я наткнулся на довольно любопытный вопрос переполнения стека от пользователя Frank:
Почему Java-метод Area # equals не переопределяет Object # equals?
Интересно, что существует Area.equals(Area)
который действительно принимает аргумент Area
вместо аргумента Object
как объявлено в Object.equals()
. Это приводит к довольно неприятному поведению, как обнаружил Фрэнк:
1
2
3
4
5
6
7
8
9
|
@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 } |
Технически, правильно, что AWT Area был реализован таким образом (поскольку hashCode()
тоже не реализован), но способ, которым Java разрешает методы, и способ, которым программисты переваривают код, который был написан, как приведенный выше код, это действительно ужасная идея перегружать метод equals.
Нет статических равных, либо
Эти правила также справедливы для статических методов equals()
, таких как, например, Apache Commons Lang ‘s
1
|
ObjectUtils.equals(Object o1, Object o2) |
Путаница возникает из-за того, что вы не можете статически импортировать этот метод equals:
1
|
import static org.apache.commons.lang.ObjectUtils.equals; |
Когда вы сейчас набираете следующее:
1
|
equals(obj1, obj2); |
Вы получите ошибку компилятора:
Метод equals (Object) в типе Object не применим для аргументов (…,…)
Причина этого заключается в том, что методы, которые находятся в области действия текущего класса и его супертипов, всегда будут скрывать все, что вы импортируете таким образом. Следующее также не работает:
01
02
03
04
05
06
07
08
09
10
11
|
import static org.apache.commons.lang.ObjectUtils.defaultIfNull; public class Test { void test() { defaultIfNull( null , null ); // ^^ compilation error here } void defaultIfNull() { } } |
Подробности в этом вопросе переполнения стека .
Вывод
Вывод прост. никогда не перегружайте ни один из методов, объявленных в Object
(переопределение, конечно, хорошо). Это включает:
-
clone()
-
equals()
-
finalize()
-
getClass()
-
hashCode()
-
notify()
-
notifyAll()
-
toString()
-
wait()
Конечно, было бы замечательно, если бы эти методы не были объявлены в Object
в первую очередь, но этот корабль отплыл 20 лет назад.
Ссылка: | Не называй свой метод «Равным» от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и JOOQ . |