24. nov. 2004

Link: Effective Java - Tips & tricks - What about equals()?

Effective Java: "Joshua Bloch's book Effective Java Programming Language Guide" is about tips and tricks about java.


This book i really recommend.

The only thing is, that the implementation of equals should be made different.

In stead of:

public boolean equals(Object o) {
if (! (o instanceof MyObject)) {
return false;
}
MyObject other = (MyObject) o;
return (value == null ? other.value == null :
value.equals(other.value));
}


Use:

public boolean equals(Object o) {
if ((o == null) || (this.getClass() != o.getClass())) {
return false;
}
MyObject other = (MyObject) o;
return (value == null ? other.value == null :
value.equals(other.value));
}


The reason to use getClass() instead of instanceof, is the problem when you have inheritance.
The equals must be symmetric, which means if a.equals(b) then b.equals(c) must be true.

Example:

... Class A...
public boolean equalsFalse(Object o) {
if (! (o instanceof A)) {
return false;
}
...
}
}


... Class B extends A...
public boolean equalsFalse(Object o) {
if (! (o instanceof B)) {
return false;
}
...
}
}


In this case this would happen:

A a = new A();
B b = new B();

a.equals(b); <- would return true
b.equals(a); <- would return false


If you use getClass() you will instead get:

a.equals(b); <- would return false
b.equals(a); <- would return false.
Which means the symmetric isn't broke!



I've made some tests that shows that getClass() takes about 7% longer time to evaluate than instanceof.
But this is a price I would like to pay to be sure that I don't have any problems with inheritance.

Ingen kommentarer: