デフォルトの.equalsと.hashCodeはクラスでどのように機能しますか?


106

自分のクラスがあるとしましょう

public class MyObj { /* ... */ }

いくつかの属性とメソッドがあります。これは、equalsを実装せず、hashCodeを実装しません。

equalsとhashCodeを呼び出したら、デフォルトの実装は何ですか?オブジェクトクラスから?そして、彼らは何ですか?デフォルトのequalsはどのように機能しますか?デフォルトのhashCodeはどのように機能し、何が返されますか?==それらが同じオブジェクトを参照しているかどうかをチェックするだけなので簡単ですが、equals()メソッドとhashCode()メソッドはどうですか?

回答:


94

はい、デフォルトの実装はObjectです(通常、equalsやhashCodeを再定義したクラスから継承する場合は、代わりにその実装を使用します)。

ドキュメントから:

equals

クラスObjectのequalsメソッドは、オブジェクトに対して最も識別可能な同値関係を実装します。つまり、null以外の参照値xとyについて、このメソッドは、xとyが同じオブジェクトを参照する場合(x == yの値がtrueの場合)にのみtrueを返します。

hashCode

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


50

ObjectJVM実装の1つから:

public boolean equals(Object object) {
    return this == object;
}

public int hashCode() {
    return VMMemoryManager.getIdentityHashCode(this);
}

どちらの場合も、問題のオブジェクトのメモリアドレスを比較するだけです。


7
JDKのどのバージョンから でv6u23 eapublic native int hashCode();
khachik

@kha-そうです、私はネイティブ実装の1つを追跡して、実際に何が行われたかを確認しました
Brad Mace

10

Objectにはequals()、およびhashCode()Objectにデフォルトの実装があります。独自の実装を提供しない場合は、それらが使用されます。の場合equals()、これは==比較を意味します。オブジェクトは、まったく同じオブジェクトである場合にのみ等しくなります。についてhashCode()は、Javadocに説明があります。

詳細については、Effective Java、Chapter 3(pdf)、item 8を参照してください。


1

はい、ObjectクラスからObjectを暗黙的に拡張するため。equals単に戻りますthis == objhashCode実装はネイティブです。単なる推測-オブジェクトへのポインタを返します。


2
これは、メモリ内にあるオブジェクトへのポインタですが、オブジェクトのメモリアドレスではありません。GCはオブジェクトをメモリ内で移動でき、ハッシュコードは同じままです。
ジェレミー

@ジェレミーありがとう。stackoverflow.com/questions/2427631/…興味深いかもしれません。
khachik 2010年

1

独自の実装を提供しない場合は、Objectから派生したものが使用されます。クラスインスタンスをie HashSet(実際にhashCode()を使用するすべてのコレクション)、またはオブジェクトの等価性をチェックする必要があるもの(つまりHashSetのcontains()メソッド)に配置する予定がない限り、問題ありません。そうでなければ、それがあなたが求めているものであるなら、それは正しく動作しません。

これらの方法のおかげで、独自の実装を提供するのはとても簡単ですHashCodeBuilderEqualsBuilderからのApache Commonsのラングを


(a)Objectクラスの「equals」のデフォルト実装がHashSetで正しく機能しないのはなぜですか?これは、このページの他の回答と矛盾しています。(b)Commons Langリンクをありがとう。
バジルブルク

1
@バジル:それは矛盾しないと思います。もちろん、デフォルトの実装はうまくいきます...どういうわけか、あなたが期待する方法ではありません。つまり、equals()は参照の等価性を使用するため、2つのその他の点で同一のオブジェクトは、デフォルトの実装では「異なる」ことになります。その結果、セット内にまったく同じものの2つの異なるインスタンスが存在することになります。あなたは重複を排除したいときや設定のかなり典型的な用途は...ある
パヴェルDyda

@PawełDyda:ミュータブルな型の場合、デフォルトの動作は通常正しいです。場合FooBar可変タイプの2つの異なるインスタンスへの参照である、および方法(例えばそこに存在するSomeMutatingMethodように)Foo.SomeMutatingMethod()影響を与えません。Barそれがないと同じようにFoo、その違いは不平等などのオブジェクトを考えるのに十分であるべきです。
スーパーキャット2012

0

IBMのdeveloperworksは言う:

このデフォルトの実装では、2つの参照は、まったく同じオブジェクトを参照する場合にのみ等しくなります。同様に、Objectによって提供されるhashCode()のデフォルトの実装は、オブジェクトのメモリアドレスを整数値にマッピングすることによって得られます。

ただし、特定のベンダーのJavaバージョンの正確な実装の詳細を確認するには、ソースとして使用できるかどうかを確認することをお勧めします(入手可能な場合)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.