Javaの等値演算子とObject#equalsとObjects#equalsの比較

Javaの値を比較する場合において、等値演算子とjava.lang.Object#equals(Object)メソッド、java.util.Objects#equals(Object, Object)メソッドの挙動の違いをまとめた。
今回は話を簡単にするため、値を整数（intとInteger）に限定した。

## 等値演算子
<table>
  <thead>
    <tr>
      <th rowspan="2" colspan="2">Left == Right</th>
      <th colspan="6">Left</th>
    </tr>
    <tr>
      <th>null</th>
      <th>int[1]</th>
      <th>int[1024]</th>
      <th>Integer[null]</th>
      <th>Integer[1]</th>
      <th>Integer[1024]</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th rowspan="6">Right</th>
      <th>null</th>
      <td>true</td>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
    </tr>
    <tr>
      <th>int[1]</th>
      <td>Compile Error</td>
      <td>true</td>
      <td>false</td>
      <td>NullPointerException</td>
      <td>true</td>
      <td>false</td>
    </tr>
    <tr>
      <th>int[1024]</th>
      <td>Compile Error</td>
      <td>false</td>
      <td>true</td>
      <td>NullPointerException</td>
      <td>false</td>
      <td>true</td>
    </tr>
    <tr>
      <th>Integer[null]</th>
      <td>true</td>
      <td>NullPointerException</td>
      <td>NullPointerException</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
    </tr>
    <tr>
      <th>Integer[1]</th>
      <td>false</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
      <td>true</td>
      <td>false</td>
    </tr>
    <tr>
      <th>Integer[1024]</th>
      <td>false</td>
      <td>false</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
      <td>false</td>
    </tr>
  </tbody>
</table>

## java.lang.Integer#equals(Object)
<table>
  <thead>
    <tr>
      <th rowspan="2" colspan="2">Left.equals(Right)</th>
      <th colspan="6">Left</th>
    </tr>
    <tr>
      <th>null</th>
      <th>int[1]</th>
      <th>int[1024]</th>
      <th>Integer[null]</th>
      <th>Integer[1]</th>
      <th>Integer[1024]</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th rowspan="6">Right</th>
      <th>null</th>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>NullPointerException</td>
      <td>false</td>
      <td>false</td>
    </tr>
    <tr>
      <th>int[1]</th>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>NullPointerException</td>
      <td>true</td>
      <td>false</td>
    </tr>
    <tr>
      <th>int[1024]</th>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>NullPointerException</td>
      <td>false</td>
      <td>true</td>
    </tr>
    <tr>
      <th>Integer[null]</th>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>NullPointerException</td>
      <td>false</td>
      <td>false</td>
    </tr>
    <tr>
      <th>Integer[1]</th>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>NullPointerException</td>
      <td>true</td>
      <td>false</td>
    </tr>
    <tr>
      <th>Integer[1024]</th>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>Compile Error</td>
      <td>NullPointerException</td>
      <td>false</td>
      <td>true</td>
    </tr>
  </tbody>
</table>

## 等値演算子とjava.lang.Integer#equals(Object)を比較
1. 左辺がnullまたはプリミティブの場合は、equalsメソッドを呼ぶことができないためコンパイルエラーとなる。
2. 左辺がObject[null]の場合、equalsメソッドを呼び出すことはできるが、実行時にNullPointerExceptionとなる。
3. 1 == Object[null]の場合は、実行時に右辺がUn-Boxingされた結果、NullPointerExcpetionが発生する。
4. Object[1024] == Object[1024]の結果がfalseとなっているのは、オブジェクトの同一を比較しているためである。比べて、Object[1024].equals(Object[1024])がtrueなのは、Integer#Equals(Object)によって、同値の比較処理が行われているため、正しい評価結果となる。
5. Object[1] == Object[1]がtrueとなっているのは、Integerが128までのObjectをキャッシュして保持しているためであり、同一オブジェクトと評価されtrueとなる。

## java.util.Objects#equals(Object, Object)
<table>
  <thead>
    <tr>
      <th rowspan="2" colspan="2">Objects.equals(Left, Right)</th>
      <th colspan="6">Left</th>
    </tr>
    <tr>
      <th>null</th>
      <th>int[1]</th>
      <th>int[1024]</th>
      <th>Integer[null]</th>
      <th>Integer[1]</th>
      <th>Integer[1024]</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th rowspan="6">Right</th>
      <th>null</th>
      <td>true</td>
      <td>false</td>
      <td>false</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
    </tr>
    <tr>
      <th>int[1]</th>
      <td>false</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
      <td>true</td>
      <td>false</td>
    </tr>
    <tr>
      <th>int[1024]</th>
      <td>false</td>
      <td>false</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
      <td>true</td>
    </tr>
    <tr>
      <th>Integer[null]</th>
      <td>true</td>
      <td>false</td>
      <td>false</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
    </tr>
    <tr>
      <th>Integer[1]</th>
      <td>false</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
      <td>true</td>
      <td>false</td>
    </tr>
    <tr>
      <th>Integer[1024]</th>
      <td>false</td>
      <td>false</td>
      <td>true</td>
      <td>false</td>
      <td>false</td>
      <td>true</td>
    </tr>
  </tbody>
</table>
等値演算子(==)およびjava.lang.Object#equals(Object)に比べて、期待した結果となっている。

## まとめ
オブジェクトに対して、等値演算をする場合は、java.util.Objects#equals(Object, Object)を利用することをお勧めする。
等値演算だけでなく、演算処理をする場合、Objectクラスのメソッドを呼び出す場合など、java.utilやorg.apache.commons.lang3にあるクラスとメソッドを積極的に利用するべきである。