Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Violating rule of reflexivity when overriding equals method

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?

like image 269
yagnya Avatar asked Dec 22 '22 10:12

yagnya


1 Answers

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.

like image 77
aioobe Avatar answered Dec 29 '22 01:12

aioobe