do I need to override the equals() method?

M

Marteno Rodia

Hello,

I've defined a class which, of course, silently extends
java.lang.Object, but I've added some my own attributes. Now I want to
be able to compare two objects of my class i.e. to check if they are
identical. Do I need to write my own equals() method or can I use the
inherited java.lang.Object.equals() method?

MR
 
A

Albert

Marteno Rodia a écrit :
Hello,

I've defined a class which, of course, silently extends
java.lang.Object, but I've added some my own attributes. Now I want to
be able to compare two objects of my class i.e. to check if they are
identical. Do I need to write my own equals() method or can I use the
inherited java.lang.Object.equals() method?

You could have searched a little...

Object.equals() only compare reference equality, which means it returns
true for exact same object

so if you want that equals returne true for "content identical" object,
yes you should override the equals(Object) method.

It depends on your uses. If you put object in collections and use
contains() for example, you might want to override equals.
 
L

Lew

Marteno Rodia a écrit :
I've defined a class which, of course, silently extends
You could have searched a little...

What makes you think he didn't?
Object.equals() only compare reference equality, which means it returns
true for exact same object

so if you want that equals returne true for "content identical" object,
yes you should override the equals(Object) method.

It depends on your uses. If you put object in collections and use
contains() for example, you might want to override equals.

Joshua Bloch covers this in /Effective Java/, a book you must own.

Always override 'equals()' and 'hashCode()' together if at all. Make sure
they are consistent with each other, i.e., if two instances compare equal,
they must have the same hash code. (The converse is not true.) Make sure you
involve each field that logically affects value equality.

For example, in comparing instances of a hypothetical 'Person' class, you
might involve 'nationalID' (e.g., Social Security number). Or you might
compare a combination of 'birthName', 'birthDate', 'birthPlace', 'birthGender'
and 'disambiguator'. The same field(s) would be involved in both the
'equals()' and 'hashCode()' methods.
 
A

Andreas Leitgeb

Albert said:
Marteno Rodia a écrit :

If you want to check for *identity*, then you can just use the inherited
Object.equals() and ignore the rest of this posting.
so if you want that equals returne true for "content identical" object,
yes you should override the equals(Object) method.
It depends on your uses. If you put object in collections and use
contains() for example, you might want to override equals.

In this case (or really always) if you override .equals() for a less
strict check, you *must* also override .hashCode() to be consistent
with that looser .equals(), otherwise some of the standard collections
may behave wrongly with your items.
 
R

Roedy Green

I've defined a class which, of course, silently extends
java.lang.Object, but I've added some my own attributes. Now I want to
be able to compare two objects of my class i.e. to check if they are
identical. Do I need to write my own equals() method or can I use the
inherited java.lang.Object.equals() method?

see http://mindprod.com/jgloss/equals.html
http://mindprod.com/jgloss/hashcode.html
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Think of the earth as a living organism that is being attacked by billions of bacteria whose numbers double every forty years. Either the host dies, or the virus dies, or both die."
~ Gore Vidal
 
M

Mark Rafn

Marteno Rodia said:
I've defined a class which, of course, silently extends
java.lang.Object, but I've added some my own attributes. Now I want to
be able to compare two objects of my class i.e. to check if they are
identical.
Do I need to write my own equals() method or can I use the
inherited java.lang.Object.equals() method?

The inherited one considers only identity, not content. If you can have two
instances that are completely interchangeable, you should override equals() to
indicate this. And, of course, if you override equals(), you must override
hashCode() to be consistent.

Note that there _IS_ a risk of being too liberal with equality. If two things
compare as equals, then they will replace each other in sets and map keys.
This is often desired, especially if the key fields that determine equality
are final. In the case of mutable objects, though, you often want them _NOT_
to be equal just because they happen to currently be the same. You only want
them equal if they will always be the same, and can literally be interchanged
in a collection without harm.

There are a few patterns to keep this straight:
1) you can define a new method, "equivalent(Object)", that means "currently
the same, but could later change to be different. Then your code can test
for equivalence when you want, but equals() only means "completely
interchangeable for all Collections".

2) you can be careful with using normal collections in some cases, and
Identity collections (IdentityHashMap, for instance) when you need a different
idea of equality. This usually takes more work than #1, and is easier to have
bugs creep in. But it's sometimes necessary if your object model doesn't have
a well-defined permanent equality.

3) create, use, and love immutable objects. Make all fields final, and you
then don't have to worry about two objects that are the same now, but might
later differ.
 
M

Mike Schilling

Lew said:
Joshua Bloch covers this in /Effective Java/, a book you must own.

Always override 'equals()' and 'hashCode()' together if at all. Make sure
they are consistent with each other, i.e., if two instances compare equal,
they must have the same hash code. (The converse is not true.) Make sure
you involve each field that logically affects value equality.

For example, in comparing instances of a hypothetical 'Person' class, you
might involve 'nationalID' (e.g., Social Security number). Or you might
compare a combination of 'birthName', 'birthDate', 'birthPlace',
'birthGender' and 'disambiguator'. The same field(s) would be involved in
both the 'equals()' and 'hashCode()' methods.

It occurs to me that something I'd like in an IDE is for it to let me mark
the fields that consititute my unique key, and then it can generate equals()
and hashCode() . The process is mechanical enough for the result to be at
least 90% correct.
 
M

Mike Schilling

Patricia said:
Mike Schilling wrote:

Eclipse has a hashCode and equals builder. It brings up a dialog
that
lists the local variables with check boxes, and also gives an option
to use either instanceof or class object identity to test for class
equality.

Very nice. I see that IntelliJ has it too, now that I think to look.
I like the fact that it deals with the two methods together, and
that
you only get to pick variables once for both methods, reducing the
risk of inconsistent equals and hashCode.

IntelliJ lets you choose the fields for equals() and then optionally
choose only a subset for hashCode(). That's logically correct; I'm
not sure when I'd use that flexibility, though.
 
L

Lew

Mike said:
Very nice. I see that IntelliJ has it too, now that I think to look.


IntelliJ lets you choose the fields for equals() and then optionally
choose only a subset for hashCode(). That's logically correct; I'm
not sure when I'd use that flexibility, though.

NetBeans has this feature also. Alt-Insert, "equals() and hashCode()",
checkbox the desired fields, shows side by side the checkboxes for each method
so you can do what Mike likes.

For a class 'Foonteger' with a single 'BigInteger' field 'value' (checkbox
checked) it inserted:
--------------------------------
@Override
public boolean equals( Object obj )
{
if ( obj == null )
{
return false;
}
if ( getClass() != obj.getClass() )
{
return false;
}
final Foonteger other = (Foonteger) obj;
if ( this.value != other.value &&
(this.value == null || !this.value.equals( other.value )) )
{
return false;
}
return true;
}

@Override
public int hashCode()
{
int hash = 7;
return hash;
}
 
M

Mike Schilling

Lew said:
NetBeans has this feature also. Alt-Insert, "equals() and
hashCode()", checkbox the desired fields, shows side by side the
checkboxes for each method so you can do what Mike likes.

For a class 'Foonteger' with a single 'BigInteger' field 'value'
(checkbox checked) it inserted:
--------------------------------
@Override
public boolean equals( Object obj )
{
if ( obj == null )
{
return false;
}
if ( getClass() != obj.getClass() )
{
return false;
}
final Foonteger other = (Foonteger) obj;
if ( this.value != other.value &&
(this.value == null || !this.value.equals(
other.value )) ) {
return false;
}
return true;
}

@Override
public int hashCode()
{
int hash = 7;
return hash;
}

The hash is always 7? Yes, that doesn't break anything, but ...

IntelliJ (4.5, which is a bit long in the tooth) gives

public boolean equals(Object o)
{
if (this == o) return true;
if (!(o instanceof Foonteger)) return false;

final Foonteger foonteger = (Foonteger) o;

if (value != null ? !value.equals(foonteger.value) :
foonteger.value != null) return false;

return true;
}

public int hashCode()
{
return (value != null ? value.hashCode() : 0);
}

That is, IntelliJ gives a far better hash function, and the two
disagree about equals() appplied tio subclasses.
 
L

Lew

Mike said:
The hash is always 7? Yes, that doesn't break anything, but ...

Yeah, that bothers me, too.
IntelliJ (4.5, which is a bit long in the tooth) gives

public boolean equals(Object o)
{
if (this == o) return true;
if (!(o instanceof Foonteger)) return false;

final Foonteger foonteger = (Foonteger) o;

if (value != null ? !value.equals(foonteger.value) :
foonteger.value != null) return false;

return true;
}

public int hashCode()
{
return (value != null ? value.hashCode() : 0);
}

That is, IntelliJ gives a far better hash function, and the two
disagree about equals() appplied tio subclasses.

The trouble with applying 'equals()' to subclasses is that it breaks symmetry.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top