Re: equals and hascode
On 12/18/2010 9:16 AM, Chris Uppal wrote:
Aeris wrote:
Chris Uppal wrote:
except in the extremely
rare cases where some class's instances' states are entirely reflected
in their hashCode()s.
Does it shouldn't be the case?
I'm not really sure what you are asking here ? If you are asking whether it's
a good idea for an object's state to be entirely reflected in its hash code,
then my answer is that you wouldn't ever normally have the option (see below).
A good practice is to write immutable object and in case of mutable
object, I agree with you that hashcode could throw a exception to avoid
collection or map problem.
I didn't recommend that /every/ mutable object should throw from hashCode(); my
point is only that it's a useful design /option/, and possibly a good one in
the case of the Colt library Matrix classes.
The idea is that mutability is only bad /if/ it affects the object's idea of
what it is equal to (and therefore also its hashCode()). Most objects are
either immutable or don't have that "changing-equality" property. In either
case they can go into hashed collections without problems.
The problems only come when the object has "changing-equality" AND it actually
changes (or is remotely likely to do so) while it is in the collection. It may
be that the collections the code uses are -- by design -- only used to hold
objects which have "settled down" and will never change again. Depending on
circumstances, it might, or might not, be worth the effort of adding code to
make it /impossible/ for the object to change once it had been added to the
collection. (For instance, making an immutable copy of the object and putting
that in the collection instead, or putting a boolean
neverChangeAgainEverEverEver
flag in the object.)
However, if the object has "changing-equality" and is normally mutable over its
whole lifecycle, then it /may/ make sense to add safety by throwing from
hashCode().
Note that this won't help with objects in non-hashed keyed
collections like TreeSet, which are based on compareTo() (or on a
Comparator) and probably don't use hashCode() at all.
Also, although the neverChangeAgainEverEverEver flag may sound
plausible, I'm not at all sure it's practical. The question arises:
When does it get set? At the first call to hashCode() or equals() or
compareTo() or some other instance method that *might* be called when
some collection gets a reference to the object? What if you put the
object in an ordinary List and then call Collections.sort() on the
List; should the object thereby lose its ability to mutate? If so,
why; if not, why not? I fear the management of the flag might turn
out to be more complicated than it's worth, giving rise to extra
methods like testEqualityWithoutFreezing(). And then you need to tell
the programmers when to use testEqualityWithoutFreezing() instead of
equals() and vice versa ... and isn't this at least as brittle as
telling them not to mutate an object while it's in a Map?
I do not foresee a day when programming languages that are powerful
enough to be useful will also be so safe they require no discipline on
the part of the programmers. See also "With Folded Hands" by Jack
Williamson.
--
Eric Sosman
esosman@ieee-dot-org.invalid