Here I am writing one sample code:
public class Test {
private int i;
private int j;
public Test() {
// TODO Auto-generated constructor stub
}
public Test(int i, int j)
{
this.i=i;
this.j=j;
}
}
now I am creating two objects as bellow:
Test t1= new Test(4,5);
Test t2 = new Test(4,5);
But when i am printing t1.hashcode() and t2.hashcode() they are giving different values. But as per java's general contact they should return same value. In fact, when i am doing same thing with String or Integer they are returning same hashcode(). Can anyone please explain why hashcode is different for t1 and t2 object?
But as per java's general contact they should return same value.
Java's equals-hashCode
contract requires that if two objects are equal by Object.equals
, they must have the same hashcode from Object.hashCode
. But the default implementation of Object.equals
is reference equality, and therefore two instances are the same if and only if they are the same instance.
Therefore, in particular, your two instances t1
and t2
are in fact not equal because you have not overridden Object.equals
. They are not equal as references, and therefore not equal per Object.equals
, and therefore it is acceptable for hashCode
to possibly return different values. In fact, the contract explicitly says the following:
It is not required that if two objects are unequal according to the
equals(java.lang.Object)
method, then calling thehashCode
method on each of the two objects must produce distinct integer results.
Thus, we do not have a violation of the equals-hashCode
contract here.
So, for your objects, if you want different instances to be equal per a logical definition of equality, you need to override Object.equals
:
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
if (this == obj) {
return true;
}
if (!(obj instanceof Test)) {
return false;
}
Test other = (Test)obj;
return this.i == other.i && this.j == other.j;
}
And the equals-hashCode
contract requires that you override Object.hashCode
too or you'll run into some nasty bugs:
@Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + this.i;
hash = 31 * hash + this.j;
return hash;
}
What does the contract say:
If two objects are equal according to the
equals(Object)
method, then calling thehashCode
method on each of the two objects must produce the same integer result.
Let's see if we have satisfied this requirement here. If x
and y
are instances of Test
and satisfy x.equals(y)
is true
, we have that x.i == y.i
and x.j == y.j
. Then, clearly, if we invoke x.hashCode()
and y.hashCode()
we have the invariant that at each line of execution in Test.hashCode
we will have hash
holding the same value. Clearly this is true on the first line since hash
will be 17
in both cases. It will hold on the second line since this.i
will return the same value whether this == x
or this == y
because x.i
equals y.i
. Finally, on the penultimate line, we will still have hash
being equal across both invocations because x.j
equals y.j
is true as well.
Note that there is one last piece of the contract that we haven't discussed yet. This is the requirement that hashCode
return a consistent value during a single execution of a Java application:
Whenever it is invoked on the same object more than once during an execution of a Java application, the
hashCode
method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
The necessity of this is obvious. If you change the return value from hashCode
during a single execution of the same application, you could lose your objects in hashtable-like data structures that use hashCode
to keep track of objects. In particular, this is why mutating objects that are keys in hashtable-like data structures is pure evil; don't do it. I would go so far as to argue that they should be immutable objects.
In fact, when i am doing same thing with
String
orInteger
they are returning samehashcode()
.
They've both overridden Object.equals
and Object.hashCode
.
You have not overridden the equals
method in your class so the default one will be used that belongs to Object
class.
Object class methods simply checks for the references whether they are referring to the same object or not.
Test t1 = new Test(4,5);
Test t2 = new Test(4,5);
are two different objects, if you don't override the equals
method here, they will be equal if and only if you do
Test t2 = t1;
As you are creating two different objects here, hashcode which are NOT equal because they don't refer to the same object
, hashcodes
must be differnt
Remember
MUST
be equalIf 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