Reputation: 2102
I was going through Joshua Bloch's online Chapter on "overridding equals() method". Here's the link. The following section confuses me,
Reflexivity—The first requirement says merely that an object must be equal to itself. It is hard to imagine violating this requirement unintentionally. 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.
Question - Is it possible for a collection's contain method to return false on an instance added to it?
I tried but the result returned is always true.
Upvotes: 0
Views: 953
Reputation: 26185
Here is a demonstration of a collection's contains method returning false for an object that has just been added to the collection. I took a normal equals and hashCode, generated by Eclipse, and changed the equals method to be non-reflexive. Specifically, it returns false when comparing an object to itself.
import java.util.LinkedList;
import java.util.List;
public class Test {
int someValue;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + someValue;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
// Bad. Non-reflexive. Should return true.
return false;
}
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Test other = (Test) obj;
if (someValue != other.someValue)
return false;
return true;
}
public static void main(String[] args) {
List<Test> myList = new LinkedList<Test>();
Test myObject = new Test();
myList.add(myObject);
System.out.println(myList.contains(myObject));
}
}
Upvotes: 0
Reputation: 121712
To illustrate the point, have this simple class:
class C {
private int i;
public C(int i) { this.i = i; }
}
Now, if you do:
C c1 = new C(1);
C c2 = new C(1);
List<C> l = new ArrayList<C>();
l.add(c1);
l.contains(c2)
will return false
, since c2.equals(c1)
is false
, in spite of the fact that both instances have the same constructor arguments.
This is because class C
does not override .equals()
nor .hashCode()
.
In general, each time your class is bound to be used in a Collection
of any kind, you had better override both of these methods. In this case:
// Note: final class, final member -- that makes this class immutable
final class C {
private final int i;
public C(int i) { this.i = i; }
@Override
public int hashCode() { return i; }
@Override
public boolean equals(Object o)
{
// no object equals null
if (o == null)
return false;
// an object is always equal to itself
if (this == o)
return true;
// immutable class: if the class of the other is not the same,
// objects are not equal
if (getClass() != o.getClass())
return false;
// Both objects are of the same class: check their members
return i == ((C) o).i;
}
}
Upvotes: 1
Reputation: 500247
Question - Is it possible for a collection's contain method to return false on an instance added to it?
Not unless the added object's equals()
violates the contract, as the quote from the book explains.
As suggested by @Karthik T, try this with an object whose equals()
unconditionally returns false
(thereby violating the contract).
Upvotes: 1