EXP02-J. 2つの配列の比較に Object.equals() メソッドを使わない
Javaでは、配列はオブジェクトであり、Object.equals() などのオブジェクトのメソッドをサポートしている。しかし、配列は Object が提供するメソッド以上のものはサポートしていない。したがって、配列に対して Object.equals() を使用すると、配列の「参照」のみが比較され、その「中身」は比較されない。2つの配列の中身を比較したいプログラマは、static な2引数の Arrays.equals() メソッドを使わなくてはならない。このメソッドは、両方の配列が同じ数の要素を含み、すべての対応する要素のペアが Object.equals() で等しい場合、2つの配列を等しいと見なす。言い換えれば、2つの配列は同じ順序で同じ要素を含む場合に等しくなる。参照等価性をチェックしたいなら、参照等価演算子 == と != を使うこと。
Object.equals() による2つの配列の比較は中身の等価性と誤解されることが多く、参照等価演算子を使うというより良い代替手段があるため、2つの配列の比較に Object.equals() メソッドを使用することは認められない。
違反コード
以下の違反コード例は、2つの配列の比較に Object.equals() メソッドを使っている。
int[] arr1 = new int[20]; // 0 で初期化
int[] arr2 = new int[20]; // 0 で初期化
System.out.println(arr1.equals(arr2)); // false を出力
適合コード
以下の適合コードでは、2つの配列の中身の比較に、2引数の Arrays.equals() メソッドを使っている。
int[] arr1 = new int[20]; // 0 で初期化
int[] arr2 = new int[20]; // 0 で初期化
System.out.println(Arrays.equals(arr1, arr2)); // true を出力
適合コード
以下の適合コードでは、配列の参照の比較に、参照等価演算子 == を使っている。
int[] arr1 = new int[20]; // 0 で初期化
int[] arr2 = new int[20]; // 0 で初期化
System.out.println(arr1 == arr2); // false を出力
リスク評価
配列の中身の比較に equals() メソッドや関係演算子を使うと、間違った結果が得られ、脆弱性につながる可能性がある。
|
ルール |
深刻度 |
可能性 |
自動検出 |
自動修正 |
優先度 |
レベル |
|---|---|---|---|---|---|---|
|
EXP02-J |
低 |
高 |
可 |
可 |
P9 |
L2 |
自動検出
静的解析で Object.equals() の使用を検出するのは容易である。しかし、メソッドが呼び出される対象のクラスを静的に解決できない場合もある。したがって、Object.equals() が配列型に対して呼び出されるときに、常にそれを判断できるわけではない。
| ツール | バージョン | チェッカー | 説明 |
|---|---|---|---|
| CodeSonar | 9.0p0 |
JAVA.COMPARE.EQ |
Should use equals() Instead of == |
| Coverity | 7.5 |
BAD_EQ |
Implemented |
| Klocwork |
2025.2 |
JD.EQ.ARR |
|
| Parasoft Jtest | 2024.2 | CERT.EXP02.UEIC | Do not use '==' or '!=' to compare objects |
| SonarQube | 9.9 | S2159 | Silly equality checks should not be made |
関連ガイドライン
|
CWE-595, Comparison of Object References Instead of Object Contents |
参考文献
|
[API 2006] |
|
| [Seacord 2015] |
翻訳元
これは以下のページを翻訳したものです。
EXP02-J. Do not use the Object.equals() method to compare two arrays (revision 104)
