javaの==とequalsの違いについて
解決済
回答 4
投稿
- 評価
- クリップ 0
- VIEW 1,801
package test;
public class Sample {
private int num;
private String name;
public Sample(int num, String name) {
// TODO 自動生成されたコンストラクター・スタブ
this.num = num;
this.name = name;
}
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(obj instanceof Sample){
Sample s = (Sample) obj;
return s.num == this.num;
}
return false;
}
}
上記のクラスが前提で
Sample a = new Sample(10,"a");
Sample b = new Sample(10,"b");
System.out.println(a.equals(b));
の処理をするとtrueが返ってきますが、どのような時に「==」でどんな時に「equals」を使用していいがわかりません。
使い分けはどのようにしたらいいのでしょうか?
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
参照型ではequals
プリミティブ型では==
ただし参照型でも「同じオブジェクトを指す」という条件にしたいなら==
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
Sampleオブジェクトの同一性をnumを使って判定したい場合に、equalsメソッドをオーバーライドします。
つまり、アプリケーションを設計するうえで、Sampleのインスタンスは、numが等しいなら意味的に等しい場合。
equals()をオーバーライドする場合は、hshCode()もオーバーライドしなければなりません。
a.equals(b) ならば a.hshCode() == b.hashCode() でなければならない。
これは、ハッシュマップのキーにSampleを使用することがあるからです。
ただし、ハッシュマップのキーにSampleを使用するなら、注意点があります。
Sampleのnumがインスタンス生成後に変更されるなら、equals()の比較に使用できない。
理由は、HashMapに格納した後、aの値を変更すると取り出せなくなるから。
例を示します。
package test;
import java.util.HashMap;
import java.util.Map;
public class MutableSample {
private int num;
private String name;
public MutableSample(int num, String name) {
this.num = num;
this.name = name;
}
@Override
public boolean equals(Object obj){
if(!(obj instanceof MutableSample)){
return false;
}
MutableSample s = (MutableSample) obj;
return s.num == this.num;
}
@Override
public int hashCode(){
return this.num;
}
public void setNum(int num) {
this.num = num; // 変更可能
}
public int getNum() {
return this.num;
}
}
setterを用意してnumの値を変更可能にしました。
実行例
public static void main(String[] args) {
MutableSample a = new MutableSample(10,"a");
MutableSample b = new MutableSample(10,"b");
System.out.println("a == b : " + a.equals(b));
Map<MutableSample,MutableSample> map = new HashMap<>();
map.put(a,a);
System.out.println("map.containsKey(b) : " + map.containsKey(b));
a.setNum(20);
System.out.println("map.containsKey(b) : " + map.containsKey(b));
}
インスタンスaをマップに格納したのち、aのnumの値を変更しました。
aはマップの中から取り出せなくなります。
結論
equlas()内で、比較に使用するフィールドの値が変更可能かどうか?
インスタンスを生成してから変更されることがないなら、equals()で比較しても良い。
インスタンス生成後に変更されるなら、equals()の比較に使用できない。
equals()をオーバーライドするならhashCode()もオーバーライドしなければならない。
参考
edx: Software Construction in Java
###追記(意味的に同じにしたければ)
numとnameがともに等しければ、おなじSampleオブジェクトだと判定する、という回答が抜けていました。
package test;
public class ImmutableSample {
private final int num;
private final String name;
public ImmutableSample(int num, String name) {
this.num = num;
this.name = name;
}
@Override
public boolean equals(Object obj){
if(!(obj instanceof ImmutableSample)){
return false;
}
ImmutableSample s = (ImmutableSample) obj;
return (s.num == this.num && s.name.equals(this.name));
}
@Override
public int hashCode(){
return (this.num + this.name.hashCode());
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
例えばここに田中さんと田中さんがいたとします。
==
田中さん == 田中さん
とした場合、いくら名前が同じでも別人なのでこれはfalseとなります。==という比較は「実体そのものが同一であること」の判定です。
equals
田中さん.equals(田中さん)
とした場合、equals処理の中が「同名であるか」の判断処理であれば、これはtrueとなります。equalsという比較は「equalsの処理の中身で決まる」判定です。Stringであれば「同じ事が書いてあればOK」ですし、Integerであれば「同じ数字であればOK」です。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
-1
上記のSampleクラス同士の比較の場合
aとbのハッシュコードが同一(同一インスタンス)であるかどうか確かめる時は==を用いる
aとbの持つnumが一致するかどうか確かめる場合は.equals()を用いる
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.11%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/03/04 12:52