2

質問を検索しましたが、満足のいく答えが見つかりませんでした。

jvm の Java オブジェクト ID

Cpp/C++ では、オブジェクト アドレスを使用して 2 つのオブジェクト アドレスをチェックし、2 つのオブジェクトが同じであるか、異なるオブジェクトであるが値が同じであるかを判断できます。Python では、id メソッドを使用して各オブジェクト ID を取得できます。Java では、これを行うために再実装hashCode()する必要のないメソッドはありますか? JVMによると、オブジェクトは次回解放されてリサイクルされる可能性があると思いますので、Javaにはそのような方法はありませんか? 私は正しいですか?

4

2 に答える 2

3

ここで回答を試みるつもりはありませんでしたが、修正が必要です。ドキュメントの実際の文言は次のとおりです。

合理的に実用的である限り、クラス 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 }
}
于 2013-01-21T04:59:26.347 に答える
2

答えはノーだ。Object.hashCode API によるとthe hashCode method defined by class Object does return distinct integers for distinct objects。Object.hashCode がオブジェクト アドレスに基づいていたとしても、Java オブジェクトは GC によってヒープ上で移動できるため、一意性は保証されません。

于 2013-01-21T04:47:39.167 に答える