Парни, классное дело делаете. Плагин ампликод - просто находка. Случайно на него нарвался на ютубе, теперь думаю, как же я раньше жил без него! Но пример теста, где используется HashSet изначально неверен. Хешмапы, а также структуры, основанные на них, к коим относится HashSet, должны использовать иммутабельные элементы, чтобы значение hashCode() не менялось. Но поскольку jpa-сущность неудобно делать иммутабельной, то и кейса, где мы кладём её в HashSet быть не должно. Соответственно раз нет кейса, то и теста в реальном мире быть не может. Впрочем, допускаю, что этот кейс вы сделали искусственно, чтобы разобрать, что такое hashCode.
Почему простой instanceof не подойдет? У нас же прокси хибернейтовский наследует исходный класс, следовательно для подклассов исходного класса(например прокси) instanceof вернет true. В hibernate 6.5 user guide, секции 3.4.7 написано решение как и от Влада Михалыча на стек оверфлоу (мб он это и написал там).
В реализации hashCode от ампликода, хешкод вычисляется не из полей (всех или не всех) объекта, а берётся из хешкода объекта типа Class, если я правильно понял. Сомнительно как-то. Это значит у разных объектов одного класса хешкод будет один. Т.е., если мы положим в тот же HasSet, несколько элементов такого класса, в итоге в сете останется один элемент.
Добрый день! Сомневаюсь, что есть подобная книжка, по крайней мере я о такой не слышал :) Так что рекомендую подписаться на канал тут и в телеграм: t.me/amplicode Чтобы если мы найдём еще подводных камней, то вы точно не пропустили)
Советую, почитать книгу Джошуа Блоха "Java Эффективное программирование" там есть отдельная глава про эти методы так же в фундаментальных книгах по java например Кей Хорстман "Java Библиотека профессионала. Том 1" есть глава про эти методы и там много интересного про equals, hashCode и их связку с наследованием
Добрый день! Потому что в моём случае мы отталкиваемся от имени класса. А имя класса у двух объектов будет одинаковое. Если будет прокси, то мы получим имя оригинального класса и возьмём от него хэшкод: instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashode() А если будет оригинальный класс, то сразу возьмём хэшкод: getClass().hashCode()
У нас на проекте запрещен ламбок - и я с этим абсолютно согласен. Бесполезная библиотека которая только заставляет вспоминать что и какая аннотация значит. Современные ide генерят геттеры сеттеры быстрее чем добавить ламбок анготации, зато потом все понятно и прозрачно, ентити можно читать как документацию. Где есть сеттеры значит это изменяемый параметр, а где нету значит инициализируеься только в конструкторе
Сгенерированные геттеры и сеттеры не несут никакой полезной информации. Скорее наоборот, могут смутить, если один из них нужно переопределить, добавив кастомной логики. А если тебе надо неизменяемые поля, ты же все равно сделаешь их final?
С ломбоком код становится лаконичнее, а значит понятнее. А изменение кода проще. Если тебе нужно добавить/удалить поле, изменить имя/тип поля, то надо просто это сделать. Не надо создавать/изменять геттеры и сеттеры, изменять конструкторы, билдеры, equals, hashCode и прочие методы.
По кайфу брат, чёткий базар держишь, разложил для пацанов всё по полочкам. Ровный ты чувак, респект и уважуха со всего нашего района
Спасибо большое!
Камент агонь
Парни, классное дело делаете. Плагин ампликод - просто находка. Случайно на него нарвался на ютубе, теперь думаю, как же я раньше жил без него!
Но пример теста, где используется HashSet изначально неверен. Хешмапы, а также структуры, основанные на них, к коим относится HashSet, должны использовать иммутабельные элементы, чтобы значение hashCode() не менялось. Но поскольку jpa-сущность неудобно делать иммутабельной, то и кейса, где мы кладём её в HashSet быть не должно. Соответственно раз нет кейса, то и теста в реальном мире быть не может.
Впрочем, допускаю, что этот кейс вы сделали искусственно, чтобы разобрать, что такое hashCode.
Спасибо за видео. Только начал изучать спринг, больше бы таких видосов с фишками и лучшими практиками
Спасибо за фидбек! Обязательно продолжим выпускать подобный контент :)
Почему простой instanceof не подойдет? У нас же прокси хибернейтовский наследует исходный класс, следовательно для подклассов исходного класса(например прокси) instanceof вернет true. В hibernate 6.5 user guide, секции 3.4.7 написано решение как и от Влада Михалыча на стек оверфлоу (мб он это и написал там).
В реализации hashCode от ампликода, хешкод вычисляется не из полей (всех или не всех) объекта, а берётся из хешкода объекта типа Class, если я правильно понял. Сомнительно как-то. Это значит у разных объектов одного класса хешкод будет один. Т.е., если мы положим в тот же HasSet, несколько элементов такого класса, в итоге в сете останется один элемент.
Нет, в сете останутся элементы, с одинаковым hashCode и equals
Какую книгу посоветуете о подобных нюансах?
Добрый день! Сомневаюсь, что есть подобная книжка, по крайней мере я о такой не слышал :)
Так что рекомендую подписаться на канал тут и в телеграм: t.me/amplicode
Чтобы если мы найдём еще подводных камней, то вы точно не пропустили)
Советую, почитать книгу Джошуа Блоха "Java Эффективное программирование" там есть отдельная глава про эти методы так же в фундаментальных книгах по java например Кей Хорстман "Java Библиотека профессионала. Том 1" есть глава про эти методы и там много интересного про equals, hashCode и их связку с наследованием
объясните, почему у разных объектов одного класса будет одинаковый hashCode в вашем варианте ?
Добрый день!
Потому что в моём случае мы отталкиваемся от имени класса. А имя класса у двух объектов будет одинаковое.
Если будет прокси, то мы получим имя оригинального класса и возьмём от него хэшкод:
instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashode()
А если будет оригинальный класс, то сразу возьмём хэшкод:
getClass().hashCode()
@@amplicode спасибо!
@@amplicode
Так если hashcode считается на основе имени класса, разве он не окажется одинаковым для абсолютно любых инстансов?
@@VasillaRobocraft окажется
Это же делает JPA Buddy, у них есть статья полностью разбирающая эту проблему.
Наша команда JPA Buddy и разрабатывала) продуктовая преемственность
Ответ в стиле - да, это я сделал😀😀😀
Зачем нужен lombok, если есть Kotlin. 😂
Зачем нужен Kotlin, если есть Scala?
У нас на проекте запрещен ламбок - и я с этим абсолютно согласен. Бесполезная библиотека которая только заставляет вспоминать что и какая аннотация значит. Современные ide генерят геттеры сеттеры быстрее чем добавить ламбок анготации, зато потом все понятно и прозрачно, ентити можно читать как документацию. Где есть сеттеры значит это изменяемый параметр, а где нету значит инициализируеься только в конструкторе
Ахахах! Бесполезная,ага) Ну если вам так сложно запомнить значения нескольких аннотаций по типу @Getter @Setter и т.д,то я вам сочувствую)
Тоже предпочитаю ломбок - кода меньше
скажи что за проект чтобы нормальные люди туда не вляпались случайно
Сгенерированные геттеры и сеттеры не несут никакой полезной информации. Скорее наоборот, могут смутить, если один из них нужно переопределить, добавив кастомной логики. А если тебе надо неизменяемые поля, ты же все равно сделаешь их final?
С ломбоком код становится лаконичнее, а значит понятнее. А изменение кода проще. Если тебе нужно добавить/удалить поле, изменить имя/тип поля, то надо просто это сделать. Не надо создавать/изменять геттеры и сеттеры, изменять конструкторы, билдеры, equals, hashCode и прочие методы.