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