Effective Java 第 2 版:第 3 章 項目 8

本項から、第 3 章「すべてのオブジェクトに共通のメソッド」に入る。

Object クラスのメソッドには、一般契約と呼ばれる使用上の決まりが存在する。 この契約を守って Object クラスのメソッドをオーバーライドしないと、契約を元に設計されている別のクラス HashMap などにおいて、Object クラスのメソッドをオーバーライドしたクラスを適切に利用できなくなる。

第 3 章では、すべてのオブジェクトに共通するメソッド、つまり Object クラスのメソッドについて、どのようにオーバーライドすべきかが述べられている。 (12 項の Comparable は例外)

equals をオーバーライドするときは一般契約に従う

equals をオーバーライドすべきとき

equals は、等価かどうか比較する必要がないとき、スーパークラスの equals で間に合っているときなどは、オーバーライドする必要はない。 つまり、それ以外の状況では、equals をオーバーライドする必要がある。

従うべき一般契約

equals をオーバーライドするときには、以下の同値関係を守る必要がある(一般契約)。 なお、以下の関係において、常に x != null, y != null, z!= null である。

  • 反射的
    • x.equals(x) == true
  • 対照的
    • x.equals(y) == true ならば y.equals(x) == true
  • 推移的
    • x.equals(y) == true かつ y.equals(z) == true ならば x.equals(z) == true
  • 整合的
    • x, y に変更がないとき、何度 x.equals(y) を呼んでも同じ値が得られる
  • 非 null 性
    • x.equals(null) == false

equals の実際の処理

equals の引数は以下のように処理していくとよい。

  1. 自分自身の参照と等価かどうか調べるために == で検査
  2. 正しい型かどうか調べるために instanceof を使って検査
  3. 引数を正しい型にキャスト
  4. 意味のある各フィールドに対して、等価かどうか検査

その他

  • equals をオーバーライドするなら hashCode もオーバーライドする
  • float, double のフィールドを比較するときは、それぞれ Float.compare, Double.compare を使う
  • Object.equals をオーバーライドする。オーバーロードしない
    • Override アノテーションを使うことで、誤ったオーバーロードを防げる

参考文献

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)