
Java超|equals()の使い方と役割
見た目が似ていても、本当に同じ戦士とは限りません。equals() を理解すると、Javaで「同じ」と判断するときに、参照先の実体を見るのか、内容を見るのかがはっきり分かるようになります。
Javaでオブジェクトを扱っていると、次のような場面が出てきます。
この2つの変数は、同じオブジェクトを指しているのか。
それとも、同じような情報を持っているだけで、別々のオブジェクトなのか。
この違いを確認したいときに使うのが equals() です。
ドラゴンボール風にたとえると、2枚の戦士登録札があるとします。
1枚目の札は悟空を指しています。
2枚目の札も同じ悟空本人を指しているかもしれません。
しかし、見た目や初期情報が似ているだけで、別に作られた戦士オブジェクトを指している可能性もあります。
このときに確認したいのは、次のことです。
| 確認したいこと | 内容 |
|---|---|
| 同じ名前の戦士か | 名前だけでは同じ実体とは限らない |
| 同じ流派の戦士か | 流派が同じでも別オブジェクトの可能性がある |
| 同じ戦士オブジェクトを指しているか | Object 由来の equals() が基本的に見るところ |
| 別々に new された戦士か | 別の実体として扱われる |
equals() は、Object クラスに用意されている基本メソッドのひとつです。
Javaのすべてのクラスは最終的に Object クラスを継承しているため、自分で equals() を書いていないクラスでも、最初から equals() を使えます。
ただし、ここで大切なのは、Object クラス由来の equals() が、最初から「名前や流派が同じかどうか」を見てくれるわけではないという点です。
Object クラス由来の equals() は、基本的には、2つの変数が同じオブジェクトを指しているかどうかを調べます。
つまり、同じような情報を持っているかではなく、同じ実体を指しているかを確認するメソッドだと考えると分かりやすいです。
この記事では、具体的なプログラムとして Sample8.java を例示しながら、equals() の役割、Object クラスとの関係、同じオブジェクトと別オブジェクトの違い、String クラスの equals() との違いを、ドラゴンボールの世界観で解説します。
equals() は何をするメソッドなのか
equals() は、あるオブジェクトと、引数として渡したオブジェクトが同じかどうかを調べるメソッドです。
基本的な形は次のようになります。
object1.equals(object2)この書き方では、object1 と object2 が同じオブジェクトかどうかを調べます。
戻り値は boolean 型です。
| 戻り値 | 意味 |
|---|---|
| true | 同じオブジェクトを指している |
| false | 違うオブジェクトを指している |
ドラゴンボール風にたとえると、warrior1 と warrior3 が同じ悟空本人を指しているなら true です。
一方、warrior1 と warrior2 が別々に作られたサイヤ人戦士なら false です。
ここでのポイントは、同じような情報を持っているかどうかではなく、同じ実体かどうかを見るということです。
たとえば、2人の戦士がどちらも次の初期値を持っていたとします。
| フィールド | 値 |
|---|---|
| name | 戦士未登録 |
| styleName | 流派未設定 |
このように中身が同じように見えても、new SaiyanWarrior() を2回実行して作られたなら、実体は別々です。
Object 由来の equals() では、基本的にこの2つは false になります。
同じオブジェクトとはどういう意味か
Javaでは、変数の中にオブジェクトそのものが丸ごと入っているわけではありません。
正確には、変数はオブジェクトを指しています。
そのため、複数の変数が同じオブジェクトを指すことがあります。
たとえば、次のようなコードを考えます。
SaiyanWarrior warrior1 = new SaiyanWarrior();
SaiyanWarrior warrior3 = warrior1;この場合、新しく作られた SaiyanWarrior オブジェクトは1つだけです。
warrior3 = warrior1; は、新しいオブジェクトを作っているのではありません。
warrior1 が指している同じオブジェクトを、warrior3 も指すようにしているだけです。
ドラゴンボール風にたとえると、1人の悟空本人に対して、warrior1 という札と warrior3 という札の2枚が向いているようなものです。
| 変数 | 指しているもの |
|---|---|
| warrior1 | 1人目の SaiyanWarrior オブジェクト |
| warrior3 | warrior1 と同じ SaiyanWarrior オブジェクト |
この場合、warrior1.equals(warrior3) は true になります。
一方で、次のように new を2回使うと、別々のオブジェクトが作られます。
SaiyanWarrior warrior1 = new SaiyanWarrior();
SaiyanWarrior warrior2 = new SaiyanWarrior();この場合、たとえ初期値が同じでも、warrior1 と warrior2 は別々のオブジェクトです。
| 変数 | 指しているもの |
|---|---|
| warrior1 | 1つ目の SaiyanWarrior オブジェクト |
| warrior2 | 2つ目の SaiyanWarrior オブジェクト |
そのため、Object クラス由来の equals() では、warrior1.equals(warrior2) は false になります。
図:equals() が true になる場合と false になる場合

この図が示していること
この図では、equals() が true になる場合と false になる場合を比較しています。
上側では、warrior1 と warrior3 が同じ SaiyanWarrior オブジェクトA を指しています。
そのため、warrior1.equals(warrior3) は true になります。
下側では、warrior1 は SaiyanWarrior オブジェクトA を指し、warrior2 は別の SaiyanWarrior オブジェクトB を指しています。
どちらも初期値は同じように見えます。
しかし、別々に作られたオブジェクトなので、warrior1.equals(warrior2) は false になります。
この図から分かることは、Object クラス由来の equals() が、見た目や初期値ではなく、同じ実体を指しているかどうかを見ているということです。
Object クラスの equals() が使える理由
equals() は、自分のクラスに毎回書かなければ使えないメソッドではありません。
Javaのすべてのクラスは、最終的に Object クラスを継承しています。
そして、equals() は Object クラスに用意されています。
そのため、次のような自作クラスでも equals() を使えます。
| クラス | equals() を使える理由 |
|---|---|
| SaiyanWarrior | Object を継承しているから |
| SuperSaiyanWarrior | SaiyanWarrior を通じて Object につながるから |
| Scouter | Object を継承しているから |
| MissionCard | Object を継承しているから |
つまり、equals() は、Javaのオブジェクトが共通して持っている基本的な比較メソッドです。
ドラゴンボール風にたとえると、戦士、スカウター、任務カードなど、どんな種類のオブジェクトでも、Java世界の共通ルールとして「同じ実体かどうか」を確認できるということです。
同じオブジェクトかどうかを調べる
ファイル名:Sample8.java
class SaiyanWarrior
{
protected String name;
protected String styleName;
public SaiyanWarrior()
{
name = "戦士未登録";
styleName = "流派未設定";
System.out.println("サイヤ人戦士を作成しました。");
}
}
class Sample8
{
public static void main(String[] args)
{
SaiyanWarrior warrior1 = new SaiyanWarrior();
SaiyanWarrior warrior2 = new SaiyanWarrior();
SaiyanWarrior warrior3;
warrior3 = warrior1;
boolean bl1 = warrior1.equals(warrior2);
boolean bl2 = warrior1.equals(warrior3);
System.out.println("warrior1とwarrior2が同じか調べたところ" + bl1 + "でした。");
System.out.println("warrior1とwarrior3が同じか調べたところ" + bl2 + "でした。");
}
}実行結果
サイヤ人戦士を作成しました。
サイヤ人戦士を作成しました。
warrior1とwarrior2が同じか調べたところfalseでした。
warrior1とwarrior3が同じか調べたところtrueでした。Sample8.java の流れ
このプログラムでは、まず次の2行で SaiyanWarrior オブジェクトを2つ作っています。
SaiyanWarrior warrior1 = new SaiyanWarrior();
SaiyanWarrior warrior2 = new SaiyanWarrior();new SaiyanWarrior() を2回実行しているため、別々のオブジェクトが2つ作られます。
| 変数 | 指しているもの |
|---|---|
| warrior1 | 1つ目の SaiyanWarrior オブジェクト |
| warrior2 | 2つ目の SaiyanWarrior オブジェクト |
この時点で、warrior1 と warrior2 は別々のオブジェクトです。
そのため、次の比較は false になります。
boolean bl1 = warrior1.equals(warrior2);次に、warrior3 を用意して、warrior1 を代入しています。
SaiyanWarrior warrior3;
warrior3 = warrior1;これは、新しいオブジェクトを作っているわけではありません。
warrior1 が指しているオブジェクトを、warrior3 も指すようにしています。
| 変数 | 指しているもの |
|---|---|
| warrior1 | 1つ目の SaiyanWarrior オブジェクト |
| warrior3 | warrior1 と同じ SaiyanWarrior オブジェクト |
そのため、次の比較は true になります。
boolean bl2 = warrior1.equals(warrior3);equals() は何を見て true と false を返しているのか
Sample8.java の比較結果を整理すると、次のようになります。
| 比較 | 結果 | 理由 |
|---|---|---|
| warrior1.equals(warrior2) | false | 別々に作られたオブジェクトだから |
| warrior1.equals(warrior3) | true | 同じオブジェクトを指しているから |
この例から分かるのは、Object クラス由来の equals() が、基本的には同じ実体を指しているかどうかを見ているということです。
ここで、warrior1 と warrior2 は、どちらも SaiyanWarrior クラスから作られています。
初期値も同じです。
| フィールド | warrior1 | warrior2 |
|---|---|---|
| name | 戦士未登録 | 戦士未登録 |
| styleName | 流派未設定 | 流派未設定 |
それでも、warrior1.equals(warrior2) は false です。
理由は、同じ値を持っているように見えても、別々に作られたオブジェクトだからです。
ドラゴンボール風にたとえると、同じ初期登録状態のサイヤ人戦士が2人いても、それぞれ別の戦士本人なら「同じ存在」とは言えない、ということです。
ドラゴンボール風に考える equals() の感覚
equals() は、ドラゴンボール風にたとえると、この2つの札は、本当に同じ戦士本人を指しているのかを確認するようなものです。
たとえば、次のように考えると分かりやすいです。
| 状況 | equals() の結果 |
|---|---|
| warrior1 は悟空本人を指している。warrior3 も同じ悟空本人を指している | true |
| warrior1 は悟空を指している。warrior2 は別に作られた別の戦士を指している | false |
| warrior1 と warrior2 は同じ名前でも、別々に作られた戦士である | 基本の equals() では false |
ここで大切なのは、同じクラスから作られているかどうかだけでは true にならないという点です。
同じ SaiyanWarrior クラスから作られていても、new によって別々に作られたオブジェクトなら、基本の equals() では false になります。
equals() が便利な場面
equals() は、複数の変数が同じオブジェクトを指しているかどうかを調べたいときに便利です。
たとえば、次のような場面です。
| 場面 | equals() が役立つ理由 |
|---|---|
| 同じオブジェクトを別名で管理していないか確認したい | 2つの変数が同じ実体を指しているか分かる |
| 配列やリストに同じオブジェクトがあるか確認したい | すでに登録済みの実体か確認できる |
| メソッドの引数で渡されたオブジェクトを確認したい | 自分が持っているオブジェクトと同じか分かる |
| オブジェクトの参照関係を学びたい | 変数と実体の違いを理解しやすい |
ドラゴンボール風にたとえると、戦士名簿の中で、この登録札はすでに登録済みのあの戦士本人を指しているのかを確認するような使い方です。
図:Object の equals() と String の equals() の違い

この図が示していること
この図では、Object クラス由来の equals() と、String クラスの equals() の違いを整理しています。
左側では、Object 由来の equals() が、同じオブジェクトを指しているかどうかを見ています。
そのため、別々に作られた SaiyanWarrior オブジェクトなら、初期値が同じでも false になります。
右側では、String クラスの equals() が、文字列の中身を見ています。
そのため、別々の String オブジェクトでも、文字列の内容が同じなら true になります。
この図から分かることは、equals() はクラスによって「同じ」の意味をオーバーライドできるということです。
String クラスの equals() は少し違う
ここで大切なのが、equals() はクラスによってオーバーライドされていることがある、という点です。
代表例が String クラスです。
String クラスの equals() は、Object クラス由来の「同じオブジェクトかどうか」をそのまま使うのではなく、文字列の内容が同じかどうかを調べるように作り直されています。
たとえば、次のような2つの文字列があるとします。
String style1 = new String("亀仙流");
String style2 = new String("亀仙流");style1 と style2 は、別々に作られた String オブジェクトです。
しかし、文字列の内容は同じです。
style1.equals(style2)この場合、String クラスの equals() では true になります。
| 比較 | Object 由来の考え方 | String の equals() |
|---|---|---|
| 別々のオブジェクトだが内容が同じ文字列 | 別物と見る | 文字列内容が同じなので true |
これは、String クラスが equals() を文字列比較用にオーバーライドしているからです。
なぜ String クラスでは内容を比較するのか
文字列では、同じオブジェクトかどうかよりも、文字として同じ内容かどうかのほうが大切になる場面が多いです。
たとえば、ドラゴンボール風に考えると、2つの流派名があるとします。
| 変数 | 内容 |
|---|---|
| style1 | 亀仙流 |
| style2 | 亀仙流 |
この2つが別々の String オブジェクトだったとしても、流派名としては同じと判断したいことが多いです。
そのため、String クラスでは equals() をオーバーライドして、文字列の内容を比較するようにしています。
つまり、equals() はクラスによって「同じ」の意味を変えられるということです。
Object の equals() と String の equals() の違い
Object クラス由来の equals() と、String クラスの equals() を比べると、違いがはっきりします。
| 比較対象 | equals() の基本的な意味 |
|---|---|
| Object クラス由来の equals() | 同じオブジェクトを指しているかを見る |
| String クラスの equals() | 文字列の内容が同じかを見る |
この違いはとても重要です。
Object の equals() は、同じ実体かどうかを見ます。
String の equals() は、文字列の内容が同じかどうかを見ます。
ドラゴンボール風にたとえると、次のようになります。
| equals() | ドラゴンボール風のイメージ |
|---|---|
| Object の equals() | 同じ戦士本人かどうかを見る |
| String の equals() | 流派名や名前の文字が同じかどうかを見る |
このように、equals() はただの比較メソッドではなく、そのクラスにとって「同じ」とは何かを表すメソッドでもあります。
ここから見える大事なこと
equals() を学ぶときに大切なのは、次の2つの見方です。
| 見方 | 内容 |
|---|---|
| Object クラス由来の基本の equals() | 同じオブジェクトかどうかを見る |
| クラスでオーバーライドされた equals() | そのクラスに合った「同じ」の意味で比較する |
今回の Sample8.java では、SaiyanWarrior クラスに equals() を定義していません。
そのため、Object クラス由来の equals() が使われています。
つまり、warrior1.equals(warrior2) は、name や styleName の値が同じかどうかではなく、同じオブジェクトを指しているかどうかを見ています。
一方で、String クラスのように equals() をオーバーライドしているクラスでは、内容を比較するように動きます。
この考え方は、オブジェクト指向らしい大切な考え方です。
クラスごとに、何をもって同じとするかを自分で定義できるからです。
図:equals() は同じの基準を表すメソッド

この図が示していること
この図では、equals() がクラスによって「同じ」の意味を変えられることを表しています。
Object クラスには equals(Object obj) があり、基本的には同じ実体を指しているかどうかを見ます。
SaiyanWarrior クラスで equals() を定義していない場合は、Object 由来の equals() が使われます。
そのため、同じ SaiyanWarrior オブジェクトを指していれば true、別々の SaiyanWarrior オブジェクトなら false になります。
一方、String クラスでは equals() がオーバーライドされています。
そのため、別々の String オブジェクトでも、文字列の内容が同じなら true になります。
この図から分かることは、equals() は単に比較するだけではなく、そのクラスにとって何を同じとみなすかを表すメソッドだということです。
ドラゴンボール風に equals() を整理する
equals() は、ドラゴンボール風にたとえると、2つの札が同じ戦士本人を指しているかを確認するためのメソッドです。
Object クラス由来の equals() は、同じ実体かどうかを見ます。
| 比較 | 判断 |
|---|---|
| 同じ戦士本人を指している | true |
| 別々に作られた戦士を指している | false |
| 名前や流派が似ているだけ | 基本の equals() では true とは限らない |
一方で、String クラスのように equals() をオーバーライドしているクラスでは、内容を見て比較することがあります。
| クラス | equals() の考え方 |
|---|---|
| Object 由来の基本 | 同じ実体かどうか |
| String | 文字列の内容が同じかどうか |
| 自作クラスでオーバーライドした場合 | そのクラスに合った同じの基準 |
つまり equals() は、単に比較するだけのメソッドではありません。
オブジェクト指向では、そのクラスにとって何を同じとみなすのかを表す重要なメソッドです。
たとえば、今後 SaiyanWarrior クラスで、name と styleName が同じなら同じ戦士として扱いたい、という設計にするなら、equals() を自分でオーバーライドすることもできます。
ただし、今回の Sample8.java では、equals() をオーバーライドしていません。
そのため、Object 由来の基本の equals() が使われ、同じ実体を指しているかどうかで true や false が決まります。
この内容で押さえておきたいポイント
| ポイント | 内容 |
|---|---|
| equals() | 2つのオブジェクトが同じかどうかを調べるメソッド |
| 定義元 | Object クラス |
| すべてのクラスで使える理由 | すべてのクラスは Object を継承しているから |
| Object 由来の equals() | 基本的には同じオブジェクトを指しているかを見る |
| new を2回使った場合 | 別々のオブジェクトなので false になる |
| 別変数に同じオブジェクトを代入した場合 | 同じ実体を指すので true になる |
| String の equals() | 文字列の内容が同じかどうかを見る |
| 大切な考え方 | クラスによって「同じ」の意味をオーバーライドできる |
equals() を理解すると、Javaでオブジェクトを比較するときに、何を見て true や false が返っているのかが分かるようになります。
特に大切なのは、Object クラス由来の equals() は、基本的には「中身が似ているか」ではなく「同じ実体を指しているか」を見ているという点です。
