山崎屋の技術メモ

IT業界で働く中でテクノロジーを愛するSIerのシステムエンジニア👨‍💻 | AndroidとWebアプリの二刀流🧙‍♂️ | コードの裏にあるストーリーを綴るブログ執筆者✍️ | 日々進化するデジタル世界で学び続ける探究者🚀 | #TechLover #CodeArtisan、気になること、メモしておきたいことを書いていきます。

Effective Java 項目8 equals をオーバーライドする時は一般契約に従う

Effective Java を再度読み直して感想や考察を書いています。

今回は項目8「equals をオーバーライドする時は一般契約に従う」を読み直してみました。

equals の一般契約

「一般契約」というと大げさですが単なるお約束。

equals のお約束は次の5つ。簡単に説明します。

反射的

x.equals(x); // → true になること。

当たり前ですね。

これが false になるソースを見たら、金魚のように口をパクパクさせるしかありません。

対称的

x.equals(y); // → true の場合
y.equals(x); // → true になること。

継承を使った場合、やらかしやすい。
書籍の中では例を交え間違いの例を紹介しています。

推移的

x.equals(y); // → true 且つ、
y.equals(z); // → true の場合、
x.equals(z); // → true になること。

整合的

要するにインスタンスの値に変更がなければ、x.equals(y) は常に同じ値を返す必要があるということです。

整合的「ではない」例として java.net.URL が紹介されていました。なんとこの URL 、equals を呼ぶとネットワーク越しに IP アドレスを取得しに行くそうです。当然ネットワークは不安定なので、複数回 x.equals(y) を呼び出すとインスタンスの中身をまったく替えていないのにもかかわらず、戻り値が異なる可能性があります。

Java の API を開発するような天才プログラマでもやらかすことはあるのですね。

非 null 性

オブジェクトは null と等しくてはいけない。x.equals(null) は必ず false になる必要があります。

その他 Tips

equals メソッドでは null チェック不要

	@Override
	public boolean equals(Object o) {
		if (o == null)	return false; // ← は不要
		if (!(o instanceof Human))
			return false;
		Human h = (Human) o;
		return name.equals(h.getName());
	}

上記で最初に行っている null チェックは不要です。o が null の場合、instanceof が false を返すからです。

java.sql.Timestamp は 一般契約を守っていない

対称的のところで「継承を使った場合、やらかしやすい」と書きましたが Timestamp がまさにそれです。

Timestamp は java.util.Date を継承してナノ秒まで保持できるように拡張されています。そして Date のインスタンスと equals を使って比較すると対照的でなくなります。

簡単な例です。

	public static void main(String[] args) {
		Date d = new Date();
		Timestamp t = new Timestamp(d.getTime());

		System.out.println(d.equals(t)); // true
		System.out.println(t.equals(d)); // false
	}

対照的でないので、同一コレクションで Date と Timdestamp それぞれのインスタンスを保持すると不整合が起きます。注意しましょう。

継承はむずかしい

前述のとおり、継承は相当注意しないと間違いを起こしやすいです。特別な事情がない限り、Effective Java 項目16 にもあるとおり「継承よりコンポジションを選ぶ」方が良いでしょう。

Effective Java 項目8のまとめ

equals の正しいオーバーライド方法が学べます。最近ではエディタが equals を自動生成してくれたりもしますが、クラスの意図に合わせ適切に修正できるように基本は抑えておきましょう。

それでは!

Effective Java 第3版

Effective Java 第3版

スッキリわかるJava入門 第2版 (スッキリシリーズ)

スッキリわかるJava入門 第2版 (スッキリシリーズ)

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門