Java のクラスがhashCode()をオーバーライドしない場合、このクラスのインスタンスを出力すると適切な一意の番号が得られます。
Object の Javadoc は、hashCode()について次のように述べています。
合理的に実用的である限り、クラス Object によって定義された hashCode メソッドは、個別のオブジェクトに対して個別の整数を返します。
しかし、クラスがhashCode()をオーバーライドする場合、一意の番号を取得するにはどうすればよいでしょうか?
System.identityHashCode(yourObject)は、yourObject の「元の」ハッシュ コードを整数として提供します。一意性は必ずしも保証されません。Sun JVM 実装は、このオブジェクトの元のメモリ アドレスに関連する値を提供しますが、これは実装の詳細であり、それに依存するべきではありません。
編集:以下のトムのコメントに従って回答が変更されました。メモリアドレスと移動オブジェクト。
Object の javadoc では、次のように指定されています。
これは通常、オブジェクトの内部アドレスを整数に変換することによって実装されますが、この実装手法は JavaTM プログラミング言語では必要ありません。
クラスが hashCode をオーバーライドする場合、それは特定の ID を生成する必要があることを意味し、これは (期待できる) 正しい動作をします。
System.identityHashCodeを使用して、任意のクラスの ID を取得できます。
hashCode()
メソッドは、オブジェクトに一意の識別子を提供するためのものではありません。むしろ、オブジェクトの状態 (メンバー フィールドの値) を 1 つの整数に分解します。この値は、ほとんどの場合、オブジェクトを効果的に格納および取得するために、マップやセットなどの一部のハッシュ ベースのデータ構造で使用されます。
オブジェクトの識別子が必要な場合は、オーバーライドする代わりに独自のメソッドを追加することをお勧めしますhashCode
。この目的のために、以下のような基本インターフェース (または抽象クラス) を作成できます。
public interface IdentifiedObject<I> {
I getId();
}
使用例:
public class User implements IdentifiedObject<Integer> {
private Integer studentId;
public User(Integer studentId) {
this.studentId = studentId;
}
@Override
public Integer getId() {
return studentId;
}
}
複数のスレッドで作成されたオブジェクトがあり、シリアライズ可能な場合に機能するこのソリューションを思いつきました。
public abstract class ObjBase implements Serializable
private static final long serialVersionUID = 1L;
private static final AtomicLong atomicRefId = new AtomicLong();
// transient field is not serialized
private transient long refId;
// default constructor will be called on base class even during deserialization
public ObjBase() {
refId = atomicRefId.incrementAndGet()
}
public long getRefId() {
return refId;
}
}
変更できるクラスの場合は、クラス変数を宣言できますstatic java.util.concurrent.atomic.AtomicInteger nextInstanceId
。(明らかな方法で初期値を与える必要があります。) 次に、インスタンス変数を宣言しますint instanceId = nextInstanceId.getAndIncrement()
。
別の角度から他の回答を補強するためだけに。
「上」のハッシュコードを再利用し、クラスの不変状態を使用して新しいものを派生させたい場合は、super の呼び出しが機能します。これは Object までカスケードする場合とカスケードしない場合がありますが (つまり、一部の祖先は super を呼び出さない場合があります)、再利用によってハッシュコードを導出できます。
@Override
public int hashCode() {
int ancestorHash = super.hashCode();
// now derive new hash from ancestorHash plus immutable instance vars (id fields)
}