結論
| 比較 | 用途 |
|---|---|
== | 参照先(メモリ上の場所)を比較 |
.equals() | 中身(値・文字列の内容)を比較 |
ただし基本データ型(プリミティブ)か参照型かで == の意味が変わるので、そこから順に整理する。
基本データ型と参照型で == の挙動が変わる
Javaの型は2系統に分かれ、== の意味も変わる。
| 型カテゴリ | 例 | == の挙動 |
|---|---|---|
| 基本データ型(プリミティブ) | int, double, boolean, char 等 | 値そのものを比較 |
| 参照型 | String, クラス全般, 配列 | **参照先(住所)**を比較 |
// 基本データ型 — 値比較
int a = 1;
int b = 1;
System.out.println(a == b); // true
// 参照型 — 住所比較
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false(住所が違う)
System.out.println(s1.equals(s2)); // true(中身が同じ)
理由はメモリ配置の違い。基本データ型はメモリ上に値そのものを置くので軽量で、== で値を直接比較できる。参照型は本体をヒープに置き、変数には住所だけを持たせる。だから == で比べられるのは「住所」になる。
参照型における「住所」のイメージ
参照型変数を「住所が書かれた紙」、オブジェクト本体を「家」、値を「家の中身」と置き換えて考えるとわかりやすい。
変数 = 住所が書かれた紙
オブジェクト = 家
中身 = 家の中にあるもの
String s1 = new String("hello");
String s2 = new String("hello");
メモリイメージ:
s1 (住所紙) ──→ 0x100番地: 家1 [中身: "hello"]
s2 (住所紙) ──→ 0x200番地: 家2 [中身: "hello"]
s1 == s2→ 「住所紙に書かれた住所が同じか?」→ falses1.equals(s2)→ 「家の中身が同じか?」→ true
リテラルプール経由なら == も true になる(たまたま)
ややこしいのは、リテラルで書いた String は内部的に共有される(リテラルプール)こと。
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
s1 == s2 // true(同じリテラルプールを参照)
s1 == s3 // false(new で別オブジェクト)
s1.equals(s3) // true(中身は同じ)
「リテラル同士なら == でも true になることがある」のは事実だが、これはたまたま同じ住所を指しているだけ。中身を比べたいときは常に .equals() を使うのが安全。
ラッパークラスの罠(Integer など)
int ではなく Integer(int のラッパークラス)を使うと、見た目は数値でも参照型なので == を使ってはいけない。
Integer i1 = 1000;
Integer i2 = 1000;
System.out.println(i1 == i2); // false(住所が違う)
System.out.println(i1.equals(i2)); // true
ラッパークラス全般(Integer, Double, Boolean, Character 等)は同じ挙動。「数値だから ==」と思い込まないのが原則。
なお Integer には -128〜127 の範囲をキャッシュする仕組みがあり、その範囲内だと == がたまたま true になる。これも「たまたま」なので、やはり .equals() を使うべき。
Integer i1 = 100;
Integer i2 = 100;
System.out.println(i1 == i2); // true(キャッシュ範囲内)
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i3 == i4); // false(キャッシュ範囲外)
まとめ
| 比較したいもの | 使うべき演算子 |
|---|---|
| 基本データ型の値 | == |
| 参照型の中身 | .equals() |
| 参照型の同一性(同じオブジェクトを指しているか) | == |
迷ったら:
- 基本データ型なら
== - 参照型なら
.equals()(「同じオブジェクトか」を本当に確かめたいときだけ==)
変更履歴
- 2026-05-02: 初版公開