Object.hashCode()
および System.identityHashCode()
はバックエンドでどのように機能しますか? identityHashCode()
はオブジェクトの参照を返しますか? hashCode()
は?に依存しますか?オブジェクトの? ==演算子バックエンドでの作業方法。
hashCode()
とidentityHashCode()
の違いは何ですか?
Object.hashCode()およびSystem.identityHashCode()は、バックエンドでどのように機能しますか?
オーバーライドされていない場合、Object.hashCode()
メソッドは単にSystem.identityHashCode(this)
を呼び出します。
System.identityHashCode(Object)
の正確な動作は、JVMの実装によって異なります。 (最近のHotspot JVMでの実際の実装はかなり賢いですが、私は余談です。)
identityHashCode()
はオブジェクトの参照を返しますか?
いいえ。これはint
を返し、int
は参照を保持できません。
identityHashCode
によって返される整数は、(a)オブジェクトのマシンアドレスに関連している可能性があります。1。 identityHashCode()
によって返される値は、オブジェクトの存続期間中は変更されないことが保証されています。つまり、GCがオブジェクトを再配置する場合(identityHashCode()
呼び出しの後)、新しいオブジェクトアドレスをIDハッシュコードとして使用できません。
HashCode()は、オブジェクトの_
?
_ _? ==
_演算子のバックエンドでの動作方法に依存しますか?.
これは意味がありません。 Javaには_? ==
_または_?==
_演算子はありません。
HashCode()とidentityHashCode()の違いは何ですか?
これは一部上で説明されています。その他の違いは次のとおりです。
hashcode()
メソッドは非最終インスタンスメソッドであり、equals(Object)
がオーバーライドされているクラスではオーバーライドする必要があります。対照的に、identityHashCode(Object)
はstatic
メソッドであるため、オーバーライドできません。
identityHashCode(Object)
メソッドは、(理論的には)ハッシュやハッシュテーブル以外の目的で使用できるオブジェクトの識別子を提供します。 (残念ながら、一意の識別子ではありませんが、は保証されていますオブジェクトの存続期間中は変更されないようにします。)
1-現在の世代のJVMの場合、メモリアドレスとはまったく関係ありません。 @bestsssの回答を参照してください。
identityHashCode()は()のように機能し、現在のところ、アドレスとは何の関係もありません。特に、アドレスは64ビット長で、整列されているため、61)
すでに生成されているものが存在するかどうかを確認し、存在する場合はそれを返します。そのint
のオブジェクトヘッダーに場所があると想定できます。
それ以外の場合:乱数を生成します(iIRCツイスターMarsaglia shift-xor アルゴリズム)、すべてのネイティブスレッドには独自のシードがあるため、共有情報はありません。オブジェクトヘッダーのidentityHashCode
フィールドをCASして、新しく生成された番号で更新します。 CASの成功が値を返す場合、そうでない場合-フィールドには、生成されたidentityHashCode
がすでに含まれています。
ハッシュコードのオーバーライドに関する残りの返信を見ることができます。
一番下の行:javadocがまだアドレスとidentityHashCodeについて何か述べている場合、誰かがそれを更新する必要があります。
これはほとんど実装固有です。あなたが得る唯一の保証は
合理的に実用的である限り、クラス
hashCode
によって定義されたObject
メソッドは、個別のオブジェクトに対して個別の整数を返します。 (これは通常、オブジェクトの内部アドレスを整数に変換することで実装されますが、この実装手法はJavaでは必要ありません。TM プログラミング言語。)
(Java 1.6 JavaDocから)
理論的には、これは値を任意に決定でき、オブジェクトごとにゼロになることさえあることを意味します。実際には、おそらくオブジェクトのアドレスから派生したものです。もちろん、これには注意が必要です。 JVMは、ガベージコレクション中にオブジェクトが適切であると考える場合、オブジェクトを再配置することができるため、メモリアドレスだけではありません。グローバルカウンター、元のオブジェクトの場所のハッシュ、または乱数ジェネレーターなどから取得できます。
identityHashCode
public static int identityHashCode(Object x)
指定されたオブジェクトのクラスがhashCode()をオーバーライドするかどうかに関係なく、デフォルトのメソッドhashCode()によって返されるのと同じ、指定されたオブジェクトのハッシュコードを返します。 null参照のハッシュコードはゼロです。
[ Java docs ]を参照してください
したがって、誰かがそのクラスのhashCode()
メソッドをオーバーライドしたが、ObjecthashCode()
によって返されるデフォルトのhashCode()
値が必要な場合System.identityHashCode()
を使用
したがって、hashCode()
は、クラスでオーバーライドしない限り、内部でSystem.identityHashCode()
を呼び出します。hashCode()をオーバーライドすると、実装を呼び出します。
上記の答えはたくさんありますが、いくつかポイントを追加する必要があります。
obj.hashCode()
と言うとき、objのコンテンツが考慮されますが、System.identityHashCode(obj)
ではコンテンツは考慮されません。したがって、2つの異なるidentityHashCode
、String
(同じ値を持つint
)は異なりますが、Hashcode
は同じになります。
String
を取得するidentityHashCode
の場合、文字列プールが重要な役割を果たします。例
Object s1 = "abcd";
Object s2 = new String("abcd");
Object s3 = "abcd";
System.out.println("identityHashCode : " + System.identityHashCode(s1) + " HashCode : " + s1.hashCode());
System.out.println("identityHashCode : " + System.identityHashCode(s2) + " HashCode : " + s2.hashCode());
System.out.println("identityHashCode : " + System.identityHashCode(s3) + " HashCode : " + s3.hashCode());
//output:
identityHashCode : 2018699554 HashCode : 2987074
identityHashCode : 1311053135 HashCode : 2987074
identityHashCode : 2018699554 HashCode : 2987074
ここでs1
とs3
は同じ参照を指しているため、s1 and s3
のidentityHashCode
は常に同じであり、s2
は異なります。
int
でも同じですが、IntegerCache
はidentityHashCode
を取得するために重要な役割を果たします
Object s1 = 5;
Object s2 = new Integer(5);
Object s3 = 5;
System.out.println("identityHashCode : " + System.identityHashCode(s1) + " HashCode : " + s1.hashCode());
System.out.println("identityHashCode : " + System.identityHashCode(s2) + " HashCode : " + s2.hashCode());
System.out.println("identityHashCode : " + System.identityHashCode(s3) + " HashCode : " + s3.hashCode());
//Output
identityHashCode : 2018699554 HashCode : 5
identityHashCode : 1311053135 HashCode : 5
identityHashCode : 2018699554 HashCode : 5