Статьи

Не называй свой метод «равным»

(конечно, если вы не переопределите 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 .