Подтвердить что ты не робот

Как реализовать равные с гибернацией, не рискуя потерять симметричное свойство?

После прочтения (опять же, должно было сделать это давным-давно) реализация equals и hashcode правильно, я пришел к этим выводам, который работает для меня:

Если pre JDK 7: Предпочитаете использовать утилиту apalsbuild и hashcodebuilder. (или Гуава). Их javadocs содержит примеры того, как их использовать в хорошем смысле.

Если JDK 7 ++: используйте класс служебных объектов

Но, если вы пишете для hibernate, появятся некоторые специальные реквизиты (см. источники дальше) Среди них рекомендуемое использование instanceof вместо getClass, из-за спящего режима, создающего прокси подклассов, которые ленивы загружены.

Но, как я понимаю, если это происходит, возникает другая потенциальная проблема: причина использования getClass заключается в обеспечении симметричного свойства равноценного контракта. JavaDocs:

*It is symmetric: for any non-null reference values x and y, x.equals(y) 
 should return true if and only if y.equals(x) returns true.*

И используя instanceof, можно не быть симметричным. Пример: B расширяет A. A equals выполняет проверку экземпляра A. B equals выполняет экземпляр проверки B. Дайте A a и B b:

a.equals(b) → true b.equals(a) → false

Как реализовать equals с hibernate, не рискуя потерять симметричное свойство? Кажется, я не безопасен при использовании getClass, и я не безопасен при использовании экземпляра?

Является ли ответ никогда не добавлять значительных членов в подклассы, а затем быть безопасным в использовании instanceof (для спящего режима, который есть)?

Источники, которые я читал:

Какие проблемы следует учитывать при переопределении equals и hashCode в Java?

Пункты 7 и 8 в Джош Блохсе отличная книга "Эффективная Java", http://web.archive.org/web/20110622072109/http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf

О Java 7: http://www.javacodegeeks.com/2012/11/guavas-objects-class-equals-hashcode-and-tostring.html

4b9b3361

Ответ 1

После того, как я подскочил, я подведу следующий вопрос:

  • Используйте instanceof, и вы никогда не сможете добавлять значимые элементы в подклассы. ( Невозможно расширить экземпляр класса и добавить компонент значения, сохраняя при этом равный контракт (Bloch)
  • Используйте getClass, и вы нарушите принцип замещения Лискова

Langers говорит http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.html

  • Тест instanceof верен только для конечных классов или если по крайней мере метод equals() является окончательным в суперклассе. Последнее по существу подразумевает, что никакой подкласс не должен расширять состояние суперкласса, но может добавьте функциональность или поля, которые не имеют отношения к объекту состояние и поведение, такие как переходные или статические поля.

Реализации с использованием теста getClass(), с другой стороны, всегда соблюдать контракт equals(); они правильны и надежны. Oни, однако, семантически сильно отличаются от реализаций, которые используйте testof test. Реализации с использованием getClass() не позволяют сравнение суб- с объектами суперкласса, даже если подкласс не добавляет никаких полей и даже не хочет переопределять equals(). Такое "тривиальное" расширение класса, например, было бы добавлением метод отладки-печати в подклассе, определенном для именно этого "тривиального" цель. Если суперкласс запрещает сравнение смешанного типа через getClass(), то тривиальное расширение не будет сравнимо к его суперклассу. Независимо от того, будет ли эта проблема полностью семантику класса и цель расширения.

Резюме. Используйте instanceof с final для equals, избегая нарушения симметрии и избегая проблемы с "спящим" спящим режимом.

Ссылки

Ответ 2

Если вы хотите сравнить классы обоих объектов в методе equals, вы можете использовать Hibernate.getClass для обоих объектов перед их сопоставлением. Тогда вы не сталкиваетесь с проблемами, например. при сравнении объекта и прокси-сервера спящего режима для объекта.

Ответ 3

Это интересный вопрос - реализация equals, поскольку отношение эквивалентности не является тривиальным, когда задействовано наследование. См. это подробное сообщение от Martin Odersky et al. о реализации равенства объектов.