That loophole about different values from run to run is solely for the
default implementation of hashcode, which is based on the actual internal
implementation of the instance.

Consider:

    class MyClass {

        int val = 1;

        public MyClass() {
        }
    }

        MyClass c1 = new MyClass();
        MyClass c2 = new MyClass();

        System.out.println("c1 hc = " + c1.hashCode());
        System.out.println("c2 hc = " + c2.hashCode());
        System.out.println("c1 == c2 " + (c1 == c2));
        System.out.println("c1 eq c2 " + (c1.equals(c2)));

c1 hc = 401424608
c2 hc = 2101440631
c1 == c2 false
c1 eq c2 false

By most accounts, these two instances (c1 and c2) are "equal". They both
have the same internal state (but are not the same object, == fails as it
should). But the default JVM equals implementation does not check the
internal state of the object.

As long as this process is running, c1 will retain it's hash code, and so
will c2. But if you run it again, there is no guarantee that these values
will be the same, just consistent within the specific executable.

But, this is not how hashCode and equals are implemented in the real world.
By default the JVM does not "properly" implement hashCode and equals. I
mean, arguably, it's accurate: here are two instances that not not "equal",
thus they don't have the same hash code. By that aspect of the contract,
it's fine. It's just not very useful, and thus requires all classes having
to implement their own versions of equals and hashCode.

Since the classes inevitably dictate the behavior of equals and hashCode,
they can "guarantee" that the values returned transcend the execution state.

You can analyze the hashCode implementation for String and discern whether
the value may change from run to run (it won't, but you can at least
check). You can discern this from any class that implements equals and
hashCode. So, for 99.999999% of the use cases of hashCode, changing values
from run to run is not an issue, and is under the developers control. The
docs simply say it can because the default implementations of hashCode do
that. The default implementation of hashCode isn't particularly useful for
most use cases.

Regards,

Will Hartung

Reply via email to