javahibernatehashcode

Java System.identityHashCode returning different value internally


The Java method System.identityHashCode(...) is returning a different value for an object when I call it internally using the this reference, compared to calling it on a variable reference of the same object.

class MyObject {
public void test(MyObject that){
        LOGGER.info("this hash: {}",System.identityHashCode(this));
        LOGGER.info("that hash: {}",System.identityHashCode(that));
        LOGGER.info("equals: {}",this == that);
    }
}

and the test...

MyObject o = new MyObject();
o.test(o);

and the output...

this hash: 263009111
that hash: 524075148
equals: false

What would cause this to happen? The real object in question is a Hibernate entity, but I've added the above test directly to the code and it's shown the same behavior in a specific scenario. Why would an object show a different identity hash code using the this keyword than it would on a reference to itself? I've also confirmed that the reference is correct by setting some fields of the object and confirming that the local fields were set to the same values. So if the reference is correct, why does identityHashCode(...) return two different values, and why does the "==" operator fail? I was under the impression that this method was specifically implemented to identify references to the same logical object?


Solution

  • They are two separate objects (even if they may conceptually contain the same data) as is demonstrated by the fact that == is false.

    System.identityHashCode()

    Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

    In other words a standard hashCode that uses just the address of the object. Every different object will give a different value. This is nothing to do with hibernate, it's how System.identityHashCode() is designed to work.

    If you want the behaviour you expect then use the equals and hashCode method on the objects hibernate has returned to you.

    You most likely have some sort of tree structure going on:

    this->A<-that

    Making changes to A whether through this or that is visible through either reference but they are still two different java objects even though they are wrapping the same inner values. This is most likely hibernate proxy objects used to support things like lazy loading of values.

    To confirm this for yourself step through it in a debugger and look at the actual objects.