> My definition of a "stateful" object is one that contains state, so
> fields defining the contents of the object (POJO, ...). For these
> objects it's almost always possible to define equality based on the
> fields and therefor I strongly advice to override both equals() and
> hashCode() (always BOTH).
Your use of "stateful" was not lost on me, nor was the fact that given
at least one instance variable in a class, you can define an equality
relation based on the field values. For that matter, statefulness is
not required -- an equality relation based on field values is trivial if
there aren't any such values. No, my assertion is that it is typically
not sensible or useful to do define such a relation.
> Most of the time these kinds of objects will be used in some way of
> storage mechanism (collections, db, ...), searching for existance of an
> object will be simplified.
Almost all objects are stateful by your definition, but most will never
be placed in a collection or array where anything other than object
identity matters. For instance, I may use a Collection to keep track of
several similar objects, but if I ever care to test for the presence of
some object, I usually want to know whether a *particular* object is
present, not whether some object with equivalent state is present.
(More often, I don't ask such questions at all.) Furthermore, I think
you are overstating your case. Your argument applies to the Collections
classes specifically. I don't see equals() having any bearing on
searching for objects in a DB, and definitely not on "...".
In any event, I think your focus on "stateful[ness]" is misplaced. I
think it was Chris Uppal who not so long ago argued here that object
state is an implementation detail in OO programming, and our attention
should instead be focused on object /behavior/. (I hope I'm
representing that accurately.) I tend to agree. On that basis, it's
not appropriate for an equals() method to attempt to answer the question
of whether some other object has the same state as this one. The
correct question is whether another object will behave the same way this
one does.
Furthermore, overriding equals() is problematic. For one thing, it
produces an inheritance problem: if you override equals() on class A in
the manner you describe, then no subclass of A can add instance
variables, implement your approach to equals(), and also retain the
symmetric nature that equals() is supposed to have. Any two of those
are exclusive of the other one.
Also, all Java objects have state that you cannot easily query, in the
form of a monitor. Even if two distinct objects of the same class have
exactly the same values for every field (object identity, even) they are
still not interchangeable when synchronization is involved.
Moreover, it is highly questionable how useful it is to query objects
with /mutable/ state about how their state compares with other objects',
because the answer may become stale even before it has been fully
determined. This is similar to the issues surrounding use of a mutable
object as a hash key, but considerably broader in scope. How is it
useful to even ask the question, much less answer it, if the answer has
an unknown duration of validity?
> For any other object I'll never override equals() nor hashCode()
> because, like you say, they do not have a better equality definition
> then simple reference comparison (x == y).
"Any other object" being any class without instance variables? Those
are the absolute easiest ones to sensibly override equals() on.
Bart Cremers - 14 Mar 2006 08:22 GMT
> > Most of the time these kinds of objects will be used in some way of
> > storage mechanism (collections, db, ...), searching for existance of an
[quoted text clipped - 10 lines]
> classes specifically. I don't see equals() having any bearing on
> searching for objects in a DB, and definitely not on "...".
Well, for the case of DB searching I'm thinking of ORM systems like
hibernate instead of plain old JDBC. All projects I've been working on
last two years use some kind of ORM in between the OO layer and the
database and there object equality needs to be defined.
> In any event, I think your focus on "stateful[ness]" is misplaced. I
> think it was Chris Uppal who not so long ago argued here that object
[quoted text clipped - 5 lines]
> correct question is whether another object will behave the same way this
> one does.
I agree on this one, object behavior is more important than object
equality, but implementing a correct equals() and hashCode() can
simplify the use of an object. With this I'm not saying you should
override them always.
> Furthermore, overriding equals() is problematic. For one thing, it
> produces an inheritance problem: if you override equals() on class A in
> the manner you describe, then no subclass of A can add instance
> variables, implement your approach to equals(), and also retain the
> symmetric nature that equals() is supposed to have. Any two of those
> are exclusive of the other one.
I don't see this one. It's pretty simple to extends the class and
override the equals() method.
> Also, all Java objects have state that you cannot easily query, in the
> form of a monitor. Even if two distinct objects of the same class have
[quoted text clipped - 8 lines]
> useful to even ask the question, much less answer it, if the answer has
> an unknown duration of validity?
Well, that's a totally different subject and for sure not to purpose of
implementing and equals() method.
> > For any other object I'll never override equals() nor hashCode()
> > because, like you say, they do not have a better equality definition
> > then simple reference comparison (x == y).
>
> "Any other object" being any class without instance variables? Those
> are the absolute easiest ones to sensibly override equals() on.
Easiest maybe, but it just makes no sense to me.
Bart
tom fredriksen - 14 Mar 2006 16:17 GMT
> Almost all objects are stateful by your definition, but most will never
> be placed in a collection or array where anything other than object
[quoted text clipped - 6 lines]
> specifically. I don't see equals() having any bearing on searching for
> objects in a DB, and definitely not on "...".
I dont quite understand what you are getting at, identity and state are
two side of the same issue. It is not possible to have an identity and
not a state, because as soon as you give an object an identity you will
also have object state. Of course you could argue that the reference is
an objects identity, but that useless as you never f.ex give an Employee
object its reference as its employee number (the identity).
The question is whether equals represents state or identity and thats up
to the designer. Additionally, some objects are data oriented and some
objects are code oriented, so the data oriented objects would of course
need its own equals() and hashCode(), while the code oriented would not
need it.
Another question is if you want to use equals as a method for comparing
object for pure equality or for locating similar objects. Pure equality
is identical state or identity, while similarity is, well..., objects
that have the same values in certain fields.
E.g. a lot of the time equals is used to find one/many objects that
matches some predefined criteria, through in equals. So any object that
matches are what you are looking for. If not then the equals code is
wrong.
> Furthermore, overriding equals() is problematic. For one thing, it
> produces an inheritance problem: if you override equals() on class A in
> the manner you describe, then no subclass of A can add instance
> variables, implement your approach to equals(), and also retain the
> symmetric nature that equals() is supposed to have. Any two of those
> are exclusive of the other one.
No, its not problematic because any subclasses would have its own
extensions and its own idea of identity and state and would therefore
need to override both methods as well.
/tom