Reputation: 830
I am having a weird issue which I am not being able to understand why this happens.
I have this equals
method implemented in a DoublyLinkedList
generic class:
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (getClass() != obj.getClass() || obj == null) {
return false;
}
DoublyLinkedList<E> other = (DoublyLinkedList<E>) obj;
if (this.size != other.size) {
return false;
}
Iterator<E> iterator = this.iterator();
Iterator<E> otherIterator = other.iterator();
while(iterator.hasNext()){
if(iterator.next() != otherIterator.next()){
return false;
}
}
return true;
}
Testing this method, in a unit test, like this:
@Test
public void testEquals() {
System.out.println("equals");
DoublyLinkedList <String> instance1 = new DoublyLinkedList <>(), instance2 = new DoublyLinkedList <>();
instance1.addLast("Xpto");
instance1.addLast("Ypto");
instance1.addLast("Zpto");
instance2.addLast("Xpto");
assertFalse("Lists should not be equal", (instance1.equals(instance2)));
assertFalse("Lists should not be equal", (instance2.equals(instance1)));
instance2.addLast("Ypto");
assertFalse("Lists should not be equal", (instance1.equals(instance2)));
assertFalse("Lists should not be equal", (instance2.equals(instance1)));
instance2.addLast("Zpto");
assertTrue("Lists should be equal", (instance1.equals(instance2)));
assertTrue("Lists should be equal", (instance2.equals(instance1)));
}
Gives me that the test passes. However, why does this happen, if I am using !=
, instead of equals
to compare each iterator's instance, in the first code? Shouldn't it compare the references, and thus fail?
Thanks in advance!
Upvotes: 2
Views: 585
Reputation: 106508
Java is interning (or caching) certain references on your behalf. Specifically, if you enter String
s as your type, you're going to run into some curious String interning behavior, in that suddenly, your lists have the same reference of String
. This is the only way that ==
would work on a reference at all - if it were somehow interned or cached and could be referenced.
This is trivial to defeat; if you use values which do not have the ability to be interned or cached, then you'll observe that your test fails.
For example, new BigInteger("100")
and new BigInteger("100")
are not the same location in memory, and if you put both of those in your list and attempt to compare equivalence, you'll get false
.
Upvotes: 2
Reputation: 758
That's because they are pointing to the same location in memory.
See: https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#d5e1634
Upvotes: 1