Equals and HashCode

  • 24
  • Недоступна
В классе Solution исправить пару методов equals/hashCode в соответствии с правилами реализации этих методов(детали уточни у своего любимого поисковика). Обе строки first и last должны принимать участие в сравнении с помощью метода equals и вычислении hashcode. Метод main не участвует в тестировании.
Вы не можете решать эту задачу, т.к. не залогинены.
Комментарии (226)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Сергей Удодов
Уровень 24, Санкт-Петербург
2 августа, 13:44
Один я не одупляю как мы без геттеров напрямую обращаемся к private полям передаваемого в equals() объекта??🤔
An N
Уровень 23, Cheboksary, Russian Federation
вчера, 05:05
Конструктор Solution объявлен как public. Туда без проблем передаем аргументы. К полям private мы не обращаемся в методе main. В этом методе обращаемся к методу equals. equals обращается к private полям. equals и private поля находятся внутри одного класса. private поля доступны внутри того же класса где эти поля.
DmitryK #853142832
Уровень 23, Alanya, Turkey
23 июля, 14:31
IDE может вместо нас реализовать equals(), но не может решить за нас одну важную задачу. Это выбор того, как сравнивать типы объектов. IDE при автосоздании метода equals() даёт нам выбор - будут ли приниматься потомки в аргументе equals: если да - то IDE использует instanceof, если нет, то getClass(). Оба варианта неидеальные: - оператор instanceof - такой способ нарушает правило транзитивности и симметричности (2 из 4 правил equals) если сравнивать родителя и потомка - метод getClass() - а это нарушит один из принципов SOLID - принцип подстановки Лисков в случае сравнения родителя и потомка (код, вызывающий equals(), не должен заботиться о том, кого он сравниванет - родителя/родителя, потомка/родителя, потомка/потомка - результат должен быть одинаков) Последствия выбора: - instanceof - может привести к тому, что x.equals(y) == true, а y.equals(x) == false. Или x.equals(y) == true, y.equals(z) == true, но x.equals(z) == false (y и z потомки x). Чтобы избежать этого, нужно либо сравнивать только объекты конечного класса в иерархии (класс будет иметь свой расширенный метод equals), либо ограничить метод equals модификатором final в суперклассе. Последнее обстоятельство означает, что наследники суперкласса имеют право только на "неважные" поля, которые не влияют на состояние. Они не должны расширять состояние суперкласса, т.к. final equals() в суперклассе ничего не знает про доп.поля и состояние дочерних классов. А потомки не могут иметь свой equals, т.к. он final в суперклассе. - getClass() - сравнение потомка и родителя всегда вернёт false, даже если все их поля равны. Можно сравнивать только объекты одного класса. Результат сравнения переменных типа "интерфейс" видимо всегда будет непредсказуемым, т.к. за такой переменной может быть как объект родительского класса, так и дочернего. Кардинальный способ избавиться от последствий - отказ от наследования в пользу композиции.
🟡ampersand
Уровень 36, Russian Federation
26 июня, 08:46
"Метод equals должен проверять является ли переданный объект объектом класса Solution." Есть два класса
public class Solution {
    public static void main(String[] args) {
        Solution solution = new Solution();
        SubSolution subSolution = new SubSolution();
        System.out.println(subSolution instanceof Solution); //true
        System.out.println(subSolution.getClass() == solution.getClass()); //false
    }
}
class SubSolution extends Solution { }
Правильное решение будет возвращать true для двух объектов разных классов. Считаю, что конструкция с getClass более подходит к требованию 3. Более того, потомок может добавить себе поля, о которых родитель и знать не будет, но выдавать true при таком сравнении. Равны ли такие объекты с точки зрения родителя - ну хз, на совести разработчика в каждом конкретном случае.
Kotamadeo
Уровень 38
19 июля, 15:25
только на 3 раз вкурил, что ему нужен instance of, а не просто getclass
Николай Лехманов
Уровень 51, Санкт-Петербург, Russian Federation
24 июня, 13:12
Кто может подробно объяснить объяснить эти две строчки: if (first != null ? !first.equals(solution.first) : solution.first != null) return false; return last != null ? last.equals(solution.last) : solution.last == null;
🟡ampersand
Уровень 36, Russian Federation
26 июня, 08:33
делишь тернарник на три части
1. first != null
2. !first.equals(solution.first)
3. solution.first != null
для условного оператора if будет применено одно из условий - 2 или 3, в зависимости от истинности первого выражения Первое - проверка на null, если верно то переходим во второе выражение и не ловим NullPointerException. Во втором выражении проверяем на равенство по содержимому полей first
if (!first.equals(solution.first))
если эти поля объекта неравны, возвращаем false. В третье выражение мы переходим, если this.first == null, значит проверяем
if (solution.first != null)
Значит если this.first == null, но solution.first != null, то поля неравны и мы возвращаем false. ! При всех остальных вариантах значений полей this.first и solution.first будут равны. Второй тернарник работает аналогично, только вместо if он передаст в return значение одного из выражений - 2 или 3, в зависимости от истинности первого. Важно понимать, что если бы у объекта были еще поля и мы бы их сравнивали такой же конструкцией:
if (first......) return false;
if (second......) return false;
if (third......) return false;
return  last != null ? last.equals(solution.last) : solution.last == null;
то к моменту выполнения последней строки c return мы гарантированно знаем, что остальные поля у объекта равны, иначе бы был выполнен return false и метод завершился. И еще по последнему тернарнику - мы бы могли просто написать
return  last.equals(solution.last);
но в таком случае, если поле null, то будет ошибка, как я писал для первого тернарника. поэтому просто добавляем проверку на null, и если last == null, проверяем ссылки
Сергей Смирнов
Уровень 36
7 июня, 04:00
"Должно быть обеспечено корректное поведение HashSet с типом элементов Solution." - Тааак и что это означает? А всё оказывается очень просто, нужно переопределить метод hashcode, но сбивает с толку такая постановка задачи, если честно.
Иван Full Stack Developer в Zona51
7 июня, 12:20
согласен К стати у тестировщиков слово "корректное" запрещено в употребление)
Anonymous #3036451
Уровень 33, Falls Church, United States
23 мая, 09:14
if (o == null || o.getClass() != Solution.class) return false;
if (o == null || o.getClass() != this.getClass()) return false;
if (o == null || !(o instanceof Solution)) return false;
P.S. ну хотя бы понял для чего писать @Override
Алексей Веденистов
Уровень 24, Москва, Россия
7 мая, 14:38
Задача простая, если хоть раз сами переопределяли equals и hashCode, ну или разбирались, как это делает Идея. Но плюс к этому надо не забыть какого типа входящий параметр.
VladimirPic Работает в Gazprom
6 мая, 18:02
Про instance of то я и забыл...
Гэндальф Серый Маг
10 апреля, 14:17
Если написать так
if(n == null || n.getClass() != this.getClass()) return false;
то валидатор не примет по третьему пункту а если написать ещё
if(n.getClass() != this.getClass()) return false;
то примёт решение, хотя Идея ругается на повтор. Такие дела.
Dmitriy Автор в t.me/ds_it
17 мая, 17:47
Удивительно, но да. Разбил на два if (проверка на равенство нулю и проверка класса). Теперь довольны и валидатор, и Идея.
Ольга
Уровень 41, Санкт-Петербург
21 марта, 16:53
Те, кто думает, что суть задачи в том, чтобы переопределить через Alt+Insert, могу сразу правильное решение копировать и сдавать, в чем смысл?)