web-dev-qa-db-ja.com

toString()とhashCode()がオーバーライドされたときに、Javaでオブジェクトの「オブジェクト参照」を取得するにはどうすればよいですか?

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

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

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

98
Nicolai

あなたはそれを使って正確に何を計画していますか(あなたがしたいことはあなたが呼ぶ必要があるものと違いをもたらします)。

hashCode 、JavaDocsで定義されているように、次のように言います:

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

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

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

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

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

100
TofuBeer

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

Integer.toHexString(System.identityHashCode(object));
48
Nicolai

二重等しい==は、オブジェクトの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"
8
noahlz

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

記録のために、IBM VM= WASサーバーで実行中の同じデフォルトのハッシュコードを持つ複数のオブジェクトを経験しました。リモートキャッシュに入れられたオブジェクトがこれは、デフォルトのハッシュコードもオブジェクトのメモリアドレスであると想定していたため、その時点で目を見張るものでした。

4
Robin

すべてのインスタンスに一意の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内で安全になります(静的を回避するためにクラスローダーでゲームをプレイしないことを想定しています)。

2
bruceg

オブジェクトクラスのtostringからコードをコピーして、stringの参照を取得できます。

class Test
{
  public static void main(String args[])
  {
    String a="nikhil";     // it stores in String constant pool
    String s=new String("nikhil");    //with new stores in heap
    System.out.println(Integer.toHexString(System.identityHashCode(a)));
    System.out.println(Integer.toHexString(System.identityHashCode(s)));
  }
}
0
Nikhil Jaitak