Ответ 1
Потому что трудно (невозможно?) Сделать это правильно, особенно симметричное свойство.
Скажем, у вас есть Vehicle
класса, а Car extends Vehicle
класса Car extends Vehicle
. Vehicle.equals()
true
если аргумент также является Vehicle
и имеет тот же вес. Если вы хотите реализовать Car.equals()
он должен давать значение true
только если аргумент также является автомобилем, и, кроме веса, он также должен сравнивать make, engine и т.д.
Теперь представьте следующий код:
Vehicle tank = new Vehicle();
Vehicle bus = new Car();
tank.equals(bus); //can be true
bus.equals(tank); //false
Первое сравнение может дать true
если по совпадению танк и автобус имеют одинаковый вес. Но так как танк - это не машина, сравнение его с машиной всегда приводит к false
.
У вас есть несколько обходных путей:
-
строгий: два объекта равны тогда и только тогда, когда они имеют одинаковый тип (и все свойства равны). Это плохо, например, когда вы создаете подкласс, чтобы добавить немного поведения или украсить исходный класс. Некоторые фреймворки также создают подклассы для ваших классов без вашего ведома (Hibernate, Spring AOP с прокси CGLIB...)
-
свободный: два объекта равны, если их типы "совместимы" и имеют одинаковое содержимое (семантически). Например, два набора равны, если они содержат одинаковые элементы, не имеет значения, что один является
HashSet
а другойTreeSet
(спасибо @veer за указание на это).Это может вводить в заблуждение. Возьмите два
LinkedHashSet
(где порядок вставки имеет значение как часть контракта). Однако, посколькуequals()
учитывает только необработанный контрактSet
, сравнение дает значениеtrue
даже для явно разных объектов:Set<Integer> s1 = new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3)); Set<Integer> s2 = new LinkedHashSet<Integer>(Arrays.asList(3, 2, 1)); System.out.println(s1.equals(s2));