equals() メソッドの実装 (1)−基本的な規約
equals() メソッドは、java.lang.Object クラスにあるメソッドで、オブジェクト同士が同じか否かを判定するものです。
初めは単純にオブジェクトの field 同士を比較するだけでよいのかと思っていたんですが、Effective Java によると、色々と細かい仕様が決まっているんですね。
実装
簡単な JavaBeans に equals() メソッドを実装した例を紹介します。
/** * 栄養成分表を表す JavaBeans */ public class NutritionFacts { // fields(簡略化のため2つにしました) /// 内容量 private int servingSize; // 1人前の量 private int servings; // constructors public NutritionFacts() { } // getter/setter は省略 // equals() /* * @see java.lang.Object#equals(java.lang.Object) */ // (1)オーバーライドのミスを防ぐため、明示的に @Override をつける。(1.5 以降) @Override public boolean equals(Object o) { // (2)instanceof で、型チェックと not null チェックを行う。 if (!(o instanceof NutritionFacts)) { return false; } // (3)参照が同一ならば、後続のチェックをせずに true を返す。結果、パフォーマンスを向上できる。 if (o == this) { return true; } // (4)既に instanceof 後なので、問題なくキャストできる。 NutritionFacts target = (NutritionFacts) o; // (5)各 field の値が同一か否かを判定する。 return (this.servingSize == target.servingSize && this.servings == target.servings); } }
仕様
Effective Java に記載されている仕様は、次の5つです。
(1)同一オブジェクトならば、true を返すこと。(reflexivity)
(2)o1.equals(o2) = true ならば、o2.equals(o1) = true であること。(symmetry)
(3)o1.equals(o2) = true かつ o2.equals(o3) = true ならば、o3.equals(o1) = true であること。(transitivity)
(4)値に変化がなければ、常に同一の結果を返すこと。(consistency:一貫性)
(5)引数が null ならば、false を返すこと。(non-nullity)
補足
上記の例では、non-nullity・reflexivity 及び consistency については理解できると思いますが、symmetry と transitivity については分かり難いのではないかと思います。
symmetry と transitivity については、別途後日コード例を記載します。