I have a doubt from the book Efective Java. The doubt is regarding equals method
reflexive rule violation. The book says the following:
"If you were to violate it and then add an instance of your class to a collection, the collection's contains method would almost certainly say that the collection did not contain the instance that you just added."
To test it I wrote an example class, but the contains method doesn't return false
It returns true
. Can anybody tell what is the problem?
I agree that the result of this program is indeed puzzling:
import java.util.*;
class Item {
@Override
public boolean equals(Object obj) {
return false; // not even equal to itself.
}
}
class Test {
public static void main(String[] args) {
Collection<Item> items = new HashSet<Item>();
Item i = new Item();
items.add(i);
System.out.println(items.contains(i)); // Prints true!
}
}
The answer is that the contains
implementation checks argument == object
before doing argument.equals(object)
. The result from contains
is true
since item == item
holds, even though item.equals(item)
returns false.
Assuming equals
follows its contract (is reflexive), this way of implementing contains
is correct.
If you read the quote you posted carefully, the author includes the word "almost" :) It seems you stumbled across one of the few exceptions to the rule.
Other collections (ArrayList
for instance) uses equals
directly, and if you change from new HashSet<Item>()
to new ArrayList<Item>()
in the above program it prints false
as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With