118

デバッグ目的で Java のオブジェクトの「オブジェクト参照」を出力したいと考えています。つまり、状況に応じてオブジェクトが同じ (または異なる) ことを確認します。

問題は、問題のクラスが別のクラスから継承されていることです。このクラスは、通常は ID を提供する toString() と hashCode() の両方をオーバーライドしています。

状況例: マルチスレッド アプリケーションを実行していて、(開発中に) すべてのスレッドがリソース オブジェクトの同じインスタンスを使用しているかどうかを確認したい場合。

4

6 に答える 6

115

それを使って正確に何をする予定ですか(何をしたいのかによって、何を呼び出す必要があるのか​​ が異なります)。

hashCodeJavaDocs で定義されているように、次のように述べています。

合理的に実用的である限り、クラス Object によって定義された hashCode メソッドは、個別のオブジェクトに対して個別の整数を返します。(これは通常、オブジェクトの内部アドレスを整数に変換することによって実装されますが、この実装手法は Java™ プログラミング言語では必要ありません。)

したがって、hashCode()それがメモリ内の一意のオブジェクトであるかどうかを調べるために使用している場合、それを行うには良い方法ではありません。

System.identityHashCode次のことを行います。

指定されたオブジェクトのクラスが hashCode() をオーバーライドするかどうかに関係なく、指定されたオブジェクトのデフォルト メソッド hashCode() によって返されるものと同じハッシュ コードを返します。null 参照のハッシュ コードはゼロです。

あなたがやっていることは、あなたがしたいことのように聞こえます...しかし、ライブラリの実装方法によっては、あなたがしたいことは安全ではないかもしれません.

于 2009-02-24T09:07:08.273 に答える
55

これが私がそれを解決した方法です:

Integer.toHexString(System.identityHashCode(object));
于 2009-02-24T08:54:07.820 に答える
9

double equals==は、オブジェクトの hashCode または equals の実装に関係なく、常にオブジェクト ID に基づいてチェックします。もちろん、比較しているオブジェクト参照がvolatile(1.5+ JVM内にある)ことを確認してください。

元の Object toString の結果が本当に必要な場合 (ユースケースの例では最適なソリューションではありませんが)、Commons Lang ライブラリには、必要な処理を行うメソッドObjectUtils.identityToString(Object)があります。JavaDoc から:

public static java.lang.String identityToString(java.lang.Object object)

クラスが toString 自体をオーバーライドしなかった場合に Object によって生成される toString を取得します。null は null を返します。

 ObjectUtils.identityToString(null)         = null
 ObjectUtils.identityToString("")           = "java.lang.String@1e23"
 ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
于 2009-02-25T04:01:48.343 に答える
5

デフォルトの hashCode() はアドレスを返さない可能性があり、言及されているように、同じ hashCode を持つ複数のオブジェクトが可能であるため、必要なことを安全に行うことはできません。目的を達成する唯一の方法は、問題のオブジェクトの hashCode() メソッドを実際にオーバーライドし、すべてのオブジェクトが一意の値を提供することを保証することです。これがあなたの状況で実現可能かどうかは別の問題です。

記録として、WAS サーバーで実行されている IBM VM で、同じデフォルトのハッシュコードを持つ複数のオブジェクトを経験しました。これにより、リモート キャッシュに配置されたオブジェクトが上書きされるという問題がありました。デフォルトのハッシュコードもオブジェクトのメモリアドレスであると想定していたので、その時点でそれは私にとって目を見張るものでした。

于 2009-02-24T14:58:07.277 に答える
3

すべてのインスタンスに一意のIDを追加します。

public interface Idable {
  int id();
}

public class IdGenerator {
  private static int id = 0;
  public static synchronized int generate() { return id++; }
}

public abstract class AbstractSomething implements Idable {
  private int id;
  public AbstractSomething () {
    this.id = IdGenerator.generate();
  }
  public int id() { return id; }
}

AbstractSomethingから拡張し、このプロパティをクエリします。単一のVM内で安全になります(統計を回避するためにクラスローダーでプレイするゲームがないと仮定します)。

于 2009-02-24T18:31:46.153 に答える