Может ли добавление методов equals () и hashCode () что-то испортить? - PullRequest
1 голос
/ 20 февраля 2020

Возможно ли, что добавление методов equals() и hashCode() нарушит уже существующий код?

У меня есть класс с 3 полями, геттерами и сеттерами:

public class Person {
private final String name;
private final List<Friend> friends;
private final Integer age;

для Для тестирования этого класса я использовал: isEqualToComparingFieldByField() метод для сравнения двух Person объектов вместо добавления equals() и hashCode(). Другое решение - переопределить equals() и hashCode() и использовать assertEquals() для сравнения этих объектов, но могу ли я быть полностью уверен, что он ничего не сломает?

Ответы [ 3 ]

12 голосов
/ 20 февраля 2020

Могу ли я быть полностью уверен, что это ничего не сломает?

Нет. Вы меняете значение равенства со ссылочной идентичности на своего рода равенство значений. Вы сломаете все, полагаясь на текущее поведение. Например, вот какой-то действительный код:

Person person1 = new Person("Foo", 100);
Person person2 = new Person("Foo", 100);
// This is fine. Two distinct Person objects will never be equal...
if (person1.equals(person2)) {
    launchNuclearMissiles();
}

Ваше предлагаемое изменение нарушит это.

У вас на самом деле есть такой код? Трудно сказать.

Скорее всего, если вы захотите изменить hashCode на включение хэшей из List<Friend>, вы можете очень легко разбить код, если тип не является неизменным. Например:

Map<Person, String> map = new HashMap<>();
Person person = new Person("Foo", 100);
map.put(person, "Some value");

// If this changes the result of hashCode()...
person.addFriend(new Friend("Bar"));
// ... then you may not be able to find even the same object in the map.
System.out.println(map.get(person));

По сути, вам необходимо знать, какой другой код использует Person, чтобы вы знали, на что он опирается. Если Person является неизменным, это делает жизнь намного проще, потому что вам не нужно беспокоиться о втором типе проблемы. (Переопределение equals() и hashCode() для изменчивых типов - дело крайне коварное.)

1 голос
/ 20 февраля 2020

Это зависит от того, где и как вы использовали объект person. Например, если вы храните человека в HashSet, HashMap et c как структура данных, тогда он может вести себя по-другому. Однако всегда рекомендуется переопределять эти методы, если вы используете какую-либо структуру данных, которая использует ha sh и равно.

0 голосов
/ 20 февраля 2020

Вы всегда должны переопределять эти методы при создании своего пользовательского класса. Если вы этого не сделаете, то используются реализации из класса Object, и эти реализации полагаются на ссылку, а не на значения полей в объектах вашего пользовательского класса.

Если вы создаете два идентичных объекта вашего пользовательского класса и вы используйте метод equals () из класса Object, чтобы сравнить их, в результате вы получите 'false'. Это потому, что хотя эти объекты идентичны, они содержат разные ссылки.

...