【はじめてのJava】equals()【いろいろなクラス編】
はじめてのJava
このシリーズでは、初めてJavaやプログラミングを勉強する方向けに、Javaによるプログラミングの基礎を説明していきます。
目標レベルは、Javaの資格試験の一つである「Oracle Certified Java Programmer, Silver」(通称Java Silver)に合格できる程度の知識の習得です。
はじめてJavaやプログラムに触れる方にもできるだけわかりやすい解説を心がけていきます。
目次
Objectクラス
Objectクラスは、Javaクラス構造を構成するルートとなるクラスです。すべてのクラスはObjectクラスの直接または間接的にこのクラスから派生しています。
また、私たちが独自に定義したクラスも暗黙的にObjectクラスを継承しています。
したがって、すべてのクラスがObjectクラスで定義されているメソッド群を継承していることになります。
今シリーズの記事では、このObjectクラスで定義されているメソッドのうち、toString(),equals(),hashCode()について3記事にわたって紹介します。
equals()
equalsメソッドは、
public boolean equals(Object obj)
と定義されており、同一性の検証を行うために用意されたメソッドです。
equals()メソッドを呼び出したオブジェクトと、引数に渡されたオブジェクトを比較してtrueまたはfalseを返します。
Objectクラスにおけるequals()メソッドの実装は非常に簡単で、二つのオブジェクトを==演算子で比較しているだけです。このとき、equals()メソッドがtrueを返すのは二つのオブジェクトの参照が同一の場合のみです。
独自に定義したクラスにおいて==演算子による比較とは異なる比較を行いたい場合、equals()メソッドをオーバーライドして実装します。
ただし、equals()メソッドをオーバーライドして独自の比較を行う際には以下の用件を満たすよう注意しなければなりません。
・メソッドの再帰性
null参照でないxに対し、x.equals(x)はtrueを返す必要がある。
・メソッドの対称性
null参照でないx、及びyに対し、x.equals(y)がtrueを返すのであればy.equals(x)もtrueを返す必要がある。
・メソッドの推移性
null参照でないx、y、zに対し、x.equals(y)がtrueを返しy.equals(z)もtrueを返す場合はx.equals(z)もtrueを返す必要がある
・メソッドの一貫性
null参照でないx及びyに対し、x.equals(y)を実行した結果は、このオブジェクトのequals()メソッドでの比較に用いる情報が変化しない限り、何度繰り返しても常に同一の結果を返す必要がある。
・null参照に対する検証性
null参照でないxに対し、x.equals(null)は常にfalseを返す必要がある。
equals()メソッドをオーバーライドする場合は、上記の要件を満たせているかどうか注意して実装しましょう。
それでは、equals()メソッドについて、サンプルコードを作成して確認してみましょう。
package blog.equals; class Obj1{ int x; int y; Obj1(int x, int y){ this.x = x; this.y = y; } } class Obj2{ int x; int y; Obj2(){ } Obj2(int x,int y){ this.x = x; this.y = y; } public boolean equals(Object o) { Obj2 obj; if(o instanceof Obj2) {//引数のオブジェクトがObj2型であるかどうかを確かめている。 obj = (Obj2) o; //Object型として渡されているため引数をObj2型へキャスト return obj.x == this.x && obj.y == this.y; } return false; //Obj2型にキャストできない場合、データ型が異なるオブジェクトとの比較になるのでfalseを返すようにする。 } } public class Sample{ public static void main(String[]args) { Obj1 obj1 = new Obj1(1,2); Obj1 obj2 = new Obj1(1,2); Obj2 obj3 = new Obj2(1,2); Obj2 obj4 = new Obj2(1,2); System.out.println(obj1.equals(obj2)); System.out.println(obj3.equals(obj4)); } }
1行目のfalseは、obj1.equals(obj2)の結果です。
Obj1クラスではequalsメソッドをオーバーライドしていないため、obj1.equals(obj2)はobj1とobj2の参照が同一であるか比較した結果を返します。今回のソースコードでは、obj1とobj2はそれぞれnewキーワードであらたにインスタンス化したオブジェクトを参照しているため、それぞれ別のオブジェクトを参照しています。よって、obj1.equals(obj2)はfalseを返します。
2行目のtrueは、obj3.equals(obj4)の結果です。
Obj2クラスでは、equalsメソッドをオーバーライドしているため、obj3.equals(obj4)は独自の方法でobj3とobj4を比較した結果を返しています。
Obj2におけるequals()メソッドは、Obj2クラスのオブジェクトが持つフィールド変数のxとyを比較した結果を返すメソッドとして定義されています。
その為、obj3とobj4は異なるオブジェクトを参照していますが、それぞれが持つフィールド変数x,yの値が一致しているため、obj3.equals(obj4)がtrueを返します。
以上のように、equalsメソッドをオーバーライドすることで、独自の方法でオブジェクトの比較を行うことが出来るようになります。オブジェクトの比較はよく使うため、equalsメソッドのオーバーライドはぜひとも押さえておきましょう。
ポイント
・equals()メソッドをオーバーライドすることで独自のルールでオブジェクトの比較を行うことが出来る。
・equals()メソッドをオーバーライドする際は、equals()メソッドの要件を満たすようにオーバーライドする。