2013-02-10 7 views
11

Po przeczytaniu się na (ponownie, powinien zrobić to już dawno temu) równych i hashcode realizacji prawidłowo doszedłem do tych wniosków, że pracuje dla mnie:W jaki sposób zaimplementować wartość równą hibernacji bez ryzyka utraty własności symetrycznej?

Jeśli pre JDK 7: Wolę użyciu Apache Commons equalsbuilder i konstruktora hashcode. (lub Guava). Ich javadocs zawierają przykłady, jak z nich korzystać w dobry sposób.

Jeżeli JDK 7 ++: Użyj nową klasę użytkową Przedmioty

ale jeśli pisanie dla hibernacji pojawić pewne szczególne requistes (patrz źródła niżej) Wśród nich są zalecane użycie instanceof zamiast getClass, ze względu na hibernację tworzenie serwerów proxy podklas, które są obciążone.

Ale jak rozumiem, jeśli to zrobi kolejny potencjalny problem: Powodem użycia getClass jest zapewnienie symetrycznej własności równego kontraktu. 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.* 

Używając instanceof, możliwe jest, że nie będzie symetryczny. przykład: B rozciąga się w równych A. nie sprawdzian instancją równych A. B w sposób sprawdzian instancją B. Daj A A i B B:

a.equals (B) -> true b.equals (a) -> false

W jaki sposób zaimplementować wartość równą hibernacji bez ryzyka utraty własności symetrycznej? Wydaje się, że nie jestem bezpieczny podczas korzystania z getClass i nie jestem bezpieczny podczas korzystania z instanceof?

Czy odpowiedź na to, aby nigdy nie dodawać znaczących członków do podklas, a następnie być bezpieczne w użyciu instanceof (do hibernacji, która jest)?

Źródła czytam:

What issues should be considered when overriding equals and hashCode in Java?

Pozycje 7 i 8 w Josh Blochs doskonałej książce "Efektywne Java", http://web.archive.org/web/20110622072109/http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf

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

Odpowiedz

2

Po Rading się trochę bardziej i podsumować to pytanie:

  • użytkowania instanceof i nigdy nie można dodać znaczących członków do podklasy.( Nie ma sposobu, aby rozszerzyć chwilowe klasę i dodać składnik wartości przy jednoczesnym zachowaniu umowy wynosi (Bloch)
  • Używaj getClass i naruszenia zasady substytucji Liskov

Langers mówi http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.html

  • Test instanceof jest poprawny tylko dla klas końcowych lub jeśli przynajmniej metoda jest równa() jest ostateczna w superklasie, ta ostatnia zasadniczo oznacza, że ​​żadna podklasa nie musi przedłużyć stanu nadklasy, ale może dodaje tylko funkcje lub pola, które są nieistotne dla stanu i zachowania obiektu, takie jak pola przejściowe lub statyczne.

Implementacje przy użyciu testu getClass() z drugiej strony zawsze są zgodne z umową equals(); są poprawne i solidne. Jednakże, są semantycznie bardzo różne od implementacji, które używają testu instanceof. Implementacje za pomocą metody getClass() nie pozwalają na porównywanie podklas z obiektami nadklasowymi nawet wtedy, gdy podklasa nie dodaje żadnych pól i nie chce nawet zastąpić equals(). Takim "banalnym" rozszerzeniem klasy byłoby na przykład dodanie metody debug-print w podklasie zdefiniowanej dla dokładnie tego "banalnego" celu, jakim jest . Jeśli superklasa zabrania porównywania typów mieszanych za pomocą testu getClass(), to proste rozszerzenie nie byłoby porównywalne z jego nadklasą: . To, czy jest to problem, czy też nie, zależy w pełni od semantyki klasy i celu rozszerzenia.

Podsumowanie - użyj instanceof z final dla equals unika łamania symetrii i unika problemu "proxy" hibernacji.

Linki

2

To jest ciekawe pytanie - implementacja equals, ponieważ relacja równoważności nie jest trywialna, gdy chodzi o dziedziczenie. Zobacz this in-depth post autorstwa Martina Odersky i in. o wprowadzaniu równości obiektów.

+0

Dzięki za linki. – Beamie

4

Jeśli chcesz porównać klas obu obiektów w metodzie równa się można wykorzystać Hibernate.getClass na obu obiektów przed ich porównanie. Wtedy nie napotkasz problemów, np. podczas porównywania obiektu i proxy do hibernacji dla obiektu.

Powiązane problemy