【Java】 等値演算子「==」と「equals」メソッドについて考える

■ はじめに

 * 値が等しいことを比較するのに、 等値演算子「==」と「equals」メソッドがある。

 ~~~~~~~~~~~~~~~~
  [1] 【値1】 == 【値2】
  [2] 【値1】.equals(【値2】)
 ~~~~~~~~~~~~~~~~

  別に基本だが、 「文字列だったらequalsメソッドを使う」という程度の認識だったが
 文字列以外にも色々と落とし穴があるので、まとめる。

 特に、後述の『例2:「127」と「128」』で「==」での比較結果が異なるのは、
 知らなかったので、勉強になった。

■(個人的な)結論

 * 『値が等しいことを比較する』ことをプログラミングする場合...
  => まず、第一に『「equals」メソッドを使う』と癖をつけておく。

 # 理由は、後述「例1」と「例2」を参照。

補足

 * int型などのプリミティブ型の比較は、「==」を使用するが、
   プリミティブ型はクラスではないので、そもそも「equals」メソッドがない。
   => なので、意識として、『「equals」メソッドを使う』と思っても問題にはならない

「equals」メソッドで比較する際の注意

【値1】.equals(【値2】)

の場合、【値1】が null の場合、NullPointErexceptionになってしまうので、注意。

ちなみに、【値1】が null 以外の場合、仮に【値2】がnullでも問題はない。
# 独自クラスで、「equals」メソッドをオーバーライドしてたら別だけど
対策
対策としては、以下の2点。
 ~~~~~~~~~~~~~~~~
 a) 【値1】はnull以外の定数を使用する
  又は、
 b) 事前にNullチェックをする
 ~~~~~~~~~~~~~~~~

■ 例

 * 例1:new Integer(【数字】)で、同じ数字なのに「equals」は等しいが、「==」は等しくない
 * 例2:「127」と「128」で、「==」での比較結果が異なる

例1:new Integer(【数字】)

* 「==」は等しくないが、「equals」は等しい
public class Main {
  public static void main(String[] args) {
    Long case1 = new Long(127);
    Long case2 = new Long(127);
    System.out.println("Case1 : == ");
    if (case1 == case2) {
      System.out.println("等しい");
    } else {
      System.out.println("等しくない");
    }

    System.out.println();

    System.out.println("Case2 : equals");
    if (case1.equals(case2)) {
      System.out.println("等しい");
    } else {
      System.out.println("等しくない");
    }
  }
}
出力結果
Case1 : == 
等しくない

Case2 : equals
等しい
なぜ?
【オブジェクト型における等値演算子「==」】
 => 『同じオブジェクトであるかをチェックする』なので、
     newしたら、例え内部のプロパティ値が同じでも比較結果は「false」となる

【オブジェクト型における「equals」メソッド】
 => 『同じ値であるかを確認』なので、比較結果は「true」となる

例2:「127」と「128」

* 「127」は等しいが「128」は等しくない!?
public class Main {
  public static void main(String[] args) {
    Long case1_1 = 127L;
    Long case1_2 = 127L;
    System.out.println("Case1 : " + case1_1);
    if (case1_1 == case1_2) {
      System.out.println("等しい");
    } else {
      System.out.println("等しくない");
    }
    
    System.out.println();
    
    Long case2_1 = 128L;
    Long case2_2 = 128L;
    System.out.println("Case2 : " + case2_1);
    if (case2_1 == case2_2) {
      System.out.println("等しい");
    } else {
      System.out.println("等しくない");
    }
  }
}
出力結果
Case1 : 127
等しい

Case2 : 128
等しくない
なぜ?
 * Longクラスはプリミティブ型のlongのラッパークラスだが、
   実は、Longクラスは内部クラスLongCacheで、-128から127までキャッシュしている。
 => 例1で、等値演算子「==」は、『同じオブジェクトであるかをチェックする』と説明したが、
 ~~~~~~~~~~~~~~~~
   a) 127の場合、キャッシュしている値同士なので比較結果は「true」
   b) 128の場合、キャッシュしている訳ではないので、newして生成するので比較結果は「false」
 ~~~~~~~~~~~~~~~~
以下を一読しておくといいかも...
http://qiita.com/hiuchida/items/8d4ee7d406334316fa82