Hacker News new | past | comments | ask | show | jobs | submit login
How To Write an Equality Method in Java (artima.com)
38 points by trjordan on June 9, 2009 | hide | past | favorite | 11 comments



> Here are four common pitfalls that can cause inconsistent behavior when overriding equals:

   1. Defining equals with the wrong signature.
   2. Changing equals without also changing hashCode.
   3. Defining equals in terms of mutable fields.
   4. Failing to define equals as an equivalence relation.
I have to call this a must read. Writing equals is straight forward, but there are are many ways to go wrong. In fact the article doesnt go far enough, because complex objects often have different levels of equality: Is it the same object, by UID or some immutable field? Is it equal by some subset of the contents? Is it equal by some classification or hierarchy?

EDIT: by different kinds of equality, I mean such things as equalByContent for mutable fields or equalByLocation.


Bloch's Effective Java is the true must read here, 80% of this article simply re-iterates what was already published there (and in other places) already. The author just adds this "canEquals" idea, which sounds like it might become annoying and hard to maintain if you have more than a small handful of subclasses to deal with.


Technically it's not a problem to define equals based on mutable data, but it is a problem to define hashCode based on mutable data. One could have a class with, say, an immutable X and a mutable Y. You probably want to check equality based on both X and Y, but hash based on X.

Or, y'know, just don't use mutable data for keys. I thought that was what people were supposed to do anyway.


Maybe languages should have special interfaces for things that can be dictionary keys? That way, when someone implements that interface, you are certifying that the object is suitable for being a key.


C++'s std::[unordered_]{map|multimap|set|multiset} containers all make const copies of keys. Of course, this being C++ you can wiggle out of this requirement (e.g. using the mutable keyword) but you have to be pretty insistant about it.

On the other hand, C++ containers have all sorts of other problems (iterator invalidation to name one)...

C# has the value type concept, but I don't think it's enforced on container keys.


I find it disappointing to see such an discussion around a Java quirk voted up here. These things are in every Java book since at least 6 years, and Java has not gained in interestingness since. Also, Eclipse tells you that with a warning if you want.

Sorry to be so negative.


> In fact, it's well known in Java that hashCode and equals should always be redefined together.

Shouldn't there be some sort of in-language capacity to address this? A "Warning: equals and hashCode not codefined" seems like it would help.


How would you know if the inherited hashCode is correct or not? Would you just assume that it isn't? That would result in lots of redundantly defined hashCode methods. Not sure that's better.


I'm over my head here, but this is the naive idea that I imagined -

You could add two keywords like /notice/ and /keep/. If a parent class's function definition of foo has /notice bar/, overrides of foo could allow the new class to inherit bar with /keep bar/, or warn if neither a keep statement or an override are present.


I would think that if both equals and hashCode are not implemented in a specific class, you would issue a warning like the parent says. I'm not sure of the details, but I assume you can disable warning for regions of code like you can in C#. So when you know you did things right, you can tell the compiler (and other coders that follow you) you know what you are doing. If you didn't do things right then the compiler reminds you to check things out. It's a win in both situations.


FindBugs does that.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: