Javaにおいて「同じ」という言葉には同じオブジェクト(インスタンス)を表す同一という意味と、
比較するオブジェクト同士の持っている値が等しい(同値である)という二つの意味がある。
- 同一である
- 同じインスタンスである。(参照が同じ)
- 同値(等価)である
- 異なるインスタンスだが同じ値を持っている。
「同一である」を判定するには == 演算子を用いて比較する。
public class User { public static void main(String[] args) { Person personA = new Person(20,"Tom"); Person personB = personA; Person personC = new Person(20,"Tom"); //trueを返す(オブジェクトが等しい) boolean result_1 = personA == personB; //falseを返す(オブジェクトが異なる) boolean result_2 = personA == personC; } }
一方、「同値(等価)である」つまりオブジェクトが持つ値が等しいかどうかの判定にはequalsメソッドを用いて比較をする。
しかし、
Objectクラスのequalsメソッドのデフォルトでの定義は同一性、すなわち同じインスタンスかどうかを確認する仕様となっている。
Objectクラスのデフォルトのequalsメソッド
public boolean equals(Object obj) { return (this == obj); }
よって、自作したオブジェクトクラスの同値性を判定したい場合、
equalsメソッドをそのクラスでオーバーライドする必要がある。
※equalsメソッドをオーバーライド実装した場合、合わせてhashCodeメソッドも定義しなければいけません。
hashCodeメソッドについてはこちらの記事にまとめています。
hashCodeメソッドについてはこちらの記事にまとめています。
作成したオブジェクトクラス内でequalsメソッドをオーバライドする。
public class Person { private int age; private String name; public Person(int age, String name) { this.age = age; this.name = name; } //Objectクラスのequalsメソッドをこのクラス内で再定義する。 @Override public boolean equals(Object obj) { if(obj instanceof Person) { Person other = (Person) obj; //変数ageと変数nameが等しければtrueを返す。(同じ値を持っているとみなす) return other.name.equals(this.name) && other.age == this.age; } return false; } }
- 12行目
- instanceof演算子でObject型で渡ってきたオブジェクトと
このクラスとの互換性をチェックする。
※同じクラス型、もしくはサブクラスかどうか。 - 13行目
- 互換性が確認出来たら、値をチェックするオブジェクトをこのクラスの型にキャストする。
- 15行目
- 同値である事の条件を定義する。
それぞれのオブジェクトの変数ageと変数nameを比較している。
すべてのフィールドが等しくなければいけないのか、
または一部のフィールドのみが一致すれば良いのか
同じ値を持っているという条件をクラスの作成時に決めることが出来る。
(設計者の判断に委ねられる)
または一部のフィールドのみが一致すれば良いのか
同じ値を持っているという条件をクラスの作成時に決めることが出来る。
(設計者の判断に委ねられる)
Eclipseの自動生成機能を利用してequalsメソッドを追加する場合
クラスファイルを右クリック、「ソース」 「hashCode()およびequals()」の生成を選ぶ。
同値の条件に含めたいフィールドにチェックを入れる。
自動生成されるequalsメソッドのソースコード
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; }
オブジェクト比較の際の同一性、同値(等価)性についてまとめました。
初めの方にも触れましたが、equalsメソッドを定義した場合は合わせてhashCodeメソッドも定義する必要が出てきます。
hashCodeメソッドについてこちらの記事も合わせて読んでいただきたいと思います。