Is this a contract-satisfying equals implementation?
Saw this in a book:
Given:
class SortOf {
String name;
int bal;
String code;
short rate;
public int hashCode() {
return (code.l开发者_如何学JAVAength() * bal);
}
}
does the following:
public boolean equals(Object o) {
return ((SortOf)o).code.length() * ((SortOf)o).bal * ((SortOf)o).rate == this.code.length() * this.bal * this.rate;
}
satisfy the equals
contract?
Suppose SortOf A
has code = "AA"; bal=2; rate=2
and SortOf B
has code = "A"; bal=4; rate=2;
Then for A
, code.length = 2
, bal = 2
, rate = 2
and B
has code.length = 1
, bal = 4
, rate=2
. Then A.equals(B)
but A.hashCode() != B.hashCode()
Apart from your other issues with the code, I believe this violates the contract.
Edited to add: Actually, it may be that this definition of equals()
technically satisfies the contract for Object.equals()
, which makes no demand on consistency with hashCode()
. It's the contract for Object.hashCode()
whose contract demands consistency with equals()
. What's that about small minds and foolish consistency...? <andersoj leaves to apply to law school>
This equals()
is reflexive, symmetric, transitive, consistent. I guess it violates the contract because .equals(null)
throws an exception rather than returning false
as required. All the equals()
spec says about hashCode()
is:
Note that it is generally necessary to override the
hashCode
method whenever this method is overridden, so as to maintain the general contract for thehashCode
method, which states that equal objects must have equal hash codes.
No.
For starters, you'll get a ClassCastException
at runtime (rather than just returning false
) if o
is not a SortOf
.
There also a general contract (see link below):
Use the same set of fields that you use to compute equals() to compute hashCode().
The methods in your question do not do this.
Excellent Q&A on this topic: What issues should be considered when overriding equals and hashCode in Java?
Joshua Bloch tells you precisely how to write and test equals and hashCode such that they conform to the contract.
Better yet, get an IDE that generates both perfectly for you. IntelliJ does a brilliant job at this and many other things.
No.
If the objects are equal, they must have the same hashcode.
However
100 * 10 * 10 = 200 * 10 * 5 (equals)
but
100 * 10 != 200 * 10 (hashCode)
In general, though, I think you develop the other way around: You have a natural idea what should make objects equal (which yours does not seem to fit), and then think about how to make a hash code to match that.
Everyone else has piped up "No", but just to add, as a general rule, many IDE environments (IE Eclipse) offer equals()/hashCode() implementation generation. Generally speaking, you'll want to do that instead. Caveat though, if you're using something like Hibernate, it's very important not to construct it in a way that goes and invokes fetching of lazy-init'd large Collections.
精彩评论