ここで回答を試みるつもりはありませんでしたが、修正が必要です。ドキュメントの実際の文言は次のとおりです。
合理的に実用的である限り、クラス Object によって定義された hashCode メソッドは、個別のオブジェクトに対して個別の整数を返します。(これは通常、オブジェクトの内部アドレスを整数に変換することによって実装されますが、この実装手法は JavaTM プログラミング言語では必要ありません。)
これは、ハッシュコードが一意であることを保証するものではなく、実装がハッシュコードを一意にしようとするだけです。さらに、64 ビットの物理アドレス (64 ビット JVM の場合) が 32 ビットのハッシュ値に折り畳まれる場合、エイリアシングが必要であり、実際にはハッシュ値ごとに 40 億のエイリアスが存在することは理にかなっています。
Java API は、オブジェクトの物理アドレスがいつでも変更される可能性があるコピー コレクターを JVM が使用できるようにするため、物理アドレスへのアクセスを許可しないようにします。
32 ビット JVM の場合でも、コピー コレクターがあり、オブジェクトのハッシュが作成時のアドレスから計算される場合、そのオブジェクトは (通常発生するように) 別の世代にコピーされます。一時的な (若い) 世代の同じ場所で作成された別の新しいオブジェクトに対して計算されます。
パフォーマンスのオーバーヘッドが原因で、Java がデフォルトで一意の ID を提供しないことは間違いありません。必要に応じて、静的カウンターを使用して独自に実装し、それぞれのコンストラクターで一意の ID を割り当てるのは簡単です。
interface ObjectWithUniqueId {
public long getId();
}
class BaseObjectWithUniqueId implements ObjectWithUniqueId {
private static long currentId = 0;
private final long id;
// TODO Synchronize me if we are in a multithreaded environment!
public BaseObjectWithUniqueId() { id = ++currentId; }
public long getId() { return id }
}