This week's book giveaways are in the Java EE and JavaScript forums.
We're giving away four copies each of The Java EE 7 Tutorial Volume 1 or Volume 2(winners choice) and jQuery UI in Action and have the authors on-line!
See this thread and this one for details.
The moose likes Java in General and the fly likes equals method Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "equals method" Watch "equals method" New topic
Author

equals method

Jeff Storey
Ranch Hand

Joined: Oct 09, 2006
Posts: 118
I have a question about the equals method. Typically, I implement the equals method as follows (assume I have some class A with a property called score):



Generally, this works fine. But what happens if I have class B that extends A and B's equals method also checks an attribute called time. Now if I call A.equals(B) where A and B have the same score, this will return true. But if I call B.equals(A), A is not an instanceof B, and thus the method will return false.

This violates the principal that equals is symmetric. The only alternative I see is by checking the actual class name, and not using instanceof, but this does not seem like an elegant solution.

Can someone comment on this and let me know if my equals is incorrect or if this is expected behavior of equals?

Thanks,
Jeff

[corrected position of the closing code tag - Ilja]
[ March 07, 2007: Message edited by: Ilja Preuss ]
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
Here's an interesting interview with Josh Bloch in which he discusses this very topic. Scroll down to instanceof versus getClass in equals Methods.

And here's a link to the relevant chapter in his book.


Some problems are so complex that you have to be highly intelligent and well informed just to be undecided about them. - Laurence J. Peter
Jeff Storey
Ranch Hand

Joined: Oct 09, 2006
Posts: 118
Thanks, I'll check it out!
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
Whoops... It seems I forgot the first link. Sorry about that.
Jeff Storey
Ranch Hand

Joined: Oct 09, 2006
Posts: 118
Garrett,

Thanks for these articles. I'm glad to see I'm not the only one thinking about these problems.

Thanks,
Jeff
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

If class A does not have 'time' how can they possibly be equal?
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38449
    
  23
My 1000th post!!

Posted by Jeff Story
checking the actual class name, and not using instanceof, but this does not seem like an elegant solution.
Nothing wrong with using class. If I remember correctly, this sort of thing ought to work:-
No use of instanceof, which the Bloch article quoted earlier shows is unreliable in this situation. You just have to make sure that all the fields which are reference types support the equals() method, rather than relying on the equals() method inherited from Object.

And less advanced readers are reminded to override the hashCode() method too.
[ March 07, 2007: Message edited by: Campbell Ritchie ]
Anupam Sinha
Ranch Hand

Joined: Apr 13, 2003
Posts: 1088
Yup! The Effective java book is great. Try composition is such scenarios.
Jeff Storey
Ranch Hand

Joined: Oct 09, 2006
Posts: 118
Thanks everyone for all of the input. Those articles were really interesting and pose some good questions. It seems like either way you do the equals method, there are some pros and cons. For my purposes, I'm going to stick with the instanceof operator.

Jeff
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
I didn't follow those links today, but I recall from prior pondering that it seems unwise (a nice word for wrong) to ever have two objects of different classes equals(). I have made some special case comparators that found objects of different types equal but that was an external evaluation, not a property of the objects. Wow, that felt like lawyer talk. Did it make sense?


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Makes sense to me. But who am I to argue?

Just be sure to pick a nice shade of paint for that corner you will be looking at it from


I been there enough times. Sometimes I even went there in defiance. But I'm too old now


I have used name based equality when comparing classes that may have been loaded from different classloaders. In the end I got scared. Maybe paranoid. Code shock?? I figured out another way...
Garrett Rowe
Ranch Hand

Joined: Jan 17, 2006
Posts: 1296
Originally posted by Stan James:
I didn't follow those links today, but I recall from prior pondering that it seems unwise (a nice word for wrong) to ever have two objects of different classes equals().


In general I agree however I do think there are special cases:



To me these should not only be considered equal but should evaluate to the same hash code. I only mention this because I've been trying my hand at a poker odds calculator, and the fastest of these use very large lookup tables to evaluate the strength of a hand. If I have sorted lists of cards in a hash set and I want to check if the hash set contains the list of cards I have in my hand, I don't want to worry about whether that list was created using a LinkedList, or ArrayList, or from Arrays.asList(), I just want an O(1) lookup that is not constantly surprising me or forcing me to think about the implementation details.

Thoughts?
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
And that's exactly what the List interface mandates. Set and Map work similarly. This can lead to strange results though, as it means that SortedSet and SortedMap can't really override these definitions without creating bigger problems. As a result, two TreeSets must be considered equal if they have the same contents, even if the sort order is different (because they use different Comparators). That's... weird, at best. So while I agree with Garrett that there are times it seems to make sense for different List implementations to evaluate as equal... there are also times this doesn't make sense.

Fortunately, any time you don't like the way that equals() has been implemented for a particular class, you can always make a new wrapper class that uses a completely different implementation. In the case of Garrett's example with evaluating poker hands, if List hadn't already been defined in a way compatible with his needs, he could have simply introduced a new class (or interface) - PokerHand or CardSet or whatever - and defined the equals() method accordingly. So in case of trouble, there's usually a workaround available. But it's important to be aware of the potential for problems with interfaces like List, Set and Map, attempting to impose a single definition of equals() on all implementations.
[ March 07, 2007: Message edited by: Jim Yingst ]

"I'm not back." - Bill Harding, Twister
 
wood burning stoves
 
subject: equals method