Checkstyle Javaルール

CheckstyleのJavaルールについて1つずつまとめます

CovariantEquals

CheckStyle公式ドキュメント

検証環境

Checkstyleバージョン:10.3.3
Javaバージョン:17


チェック概要

チェック追加バージョン
Checkstyle 3.2

共変なequals()メソッドを定義しているクラスやレコードが、equals(Object)メソッドもオーバーライドしているかどうかをチェックする。
共変なequals()メソッド:equals(Object) と同様のメソッドであるが、引数の型が共変(Objectの任意のサブクラス)なメソッドのこと。

enumはequals(Object)をオーバーライドできないが、チェック対象となる。
enumでequals()を実装すると、共変enumメソッドでは等しいのに、普通に比較すると等しくない2つの異なるenum値が存在する可能性があることを指摘するためである。

Javaクラスとレコードは、オブジェクトの等価性の述語を定義するために、equals(Object)メソッドをオーバーライドすることができる。
このメソッドはJavaランタイムライブラリクラスの多くによって使用される。例えば、汎用コンテナを実装するためなどである。

プログラマはequals()へのパラメータの型として以下のようにクラスFooの型を誤って使用することがある。

public boolean equals(Foo obj) {...}

このequals()はObjectクラスのバージョンをオーバーライドしないので、
標準のequals(Object)メソッドがオーバーライドされることを期待する標準のコレクションクラスの1つと共に使用される場合、実行時に予期しない動作につながることがある。

この種のバグは見た目が正しく、クラスが(スーパータイプではなく)クラス型の参照を通じてアクセスされる状況では、正しく動作するため、表面化されない。
しかし、コンテナの中で初めて使われた際には想定外な挙動を示す可能性がある。
このような理由から、この種のバグはテストやコード検査から漏れてしまうことがある。

設定+チェック実行結果

設定ファイル記述方法

<module name="Checker">
    <module name="TreeWalker">
        <module name="CovariantEquals"/>
    </module>
</module>

チェック実行例

// NG equals(Object)がオーバーライドされていない
class MyClass {
    public boolean equals(Test i) {
        return false;
    }
}

// OK
class MyClass {
    public boolean equals(Test i) {
        return false;
    }

    public boolean equals(Object i) {
        return false;
    }
}