
Java超|Objectクラスと継承のしくみ
どんなクラスも、たどっていけば Object につながる。Object クラスを理解すると、Javaの継承が「バラバラの親子関係」ではなく、ひとつの大きな階層として見えてきます。
Javaでは、クラスを継承によって広げていけます。
親クラスであるスーパークラスを土台にして、子クラスであるサブクラスを作ります。さらに、そのサブクラスをもう一段階拡張して、新しいサブクラスを作ることもできます。
たとえば、ドラゴンボールの世界観で考えると、まず SaiyanWarrior というサイヤ人戦士の共通クラスがあります。
そこから、SuperSaiyanWarrior というスーパーサイヤ人クラスを作れます。さらに、その SuperSaiyanWarrior を土台にして、GodSaiyanWarrior のような、より特別な戦士クラスを作ることもできます。
このように、クラス同士が親子関係でつながっていく構造を、クラスの階層といいます。
ただし、Javaの継承には大切なルールがあります。
| できること・できないこと | 内容 |
|---|---|
| 1つのスーパークラスから複数のサブクラスを作る | できる |
| サブクラスをさらに拡張する | できる |
| 1つのクラスが複数のスーパークラスを同時に継承する | できない |
| スーパークラスを書かないクラスが Object につながる | 自動的につながる |
特に重要なのが、スーパークラスを明示しないクラスは、自動的に Object クラスを親に持つというルールです。
つまり、Javaで作るすべてのクラスは、最終的には Object クラスにつながっています。
Object クラスは、Javaのあらゆるクラスにとっての共通の親です。
ドラゴンボール風にたとえると、悟空系戦士、ベジータ系戦士、悟飯系戦士、戦闘服、スカウター、任務カードなど、いろいろなクラスを作れます。
それぞれ役割は違います。
でも、Javaの世界では、すべてが最終的に Object という共通の土台につながっています。
この記事では、クラスの階層、単一継承、Object クラス、equals、getClass、toString、toString のオーバーライドについて、サイヤ人戦士の継承階層にたとえて解説していきます。
クラスの階層を作るとはどういうことか
Javaでは、1つのスーパークラスをもとにして、複数のサブクラスを作れます。
ドラゴンボール風にたとえると、まず SaiyanWarrior というサイヤ人戦士の共通クラスがあるとします。
そこから、次のようなサブクラスを作れます。
| スーパークラス | サブクラスの例 | 意味 |
|---|---|---|
| SaiyanWarrior | SuperSaiyanWarrior | スーパーサイヤ人戦士 |
| SaiyanWarrior | EliteSaiyanWarrior | エリートサイヤ人戦士 |
| SaiyanWarrior | SupportSaiyanWarrior | 支援型サイヤ人戦士 |
このように、1つの親クラスから複数の子クラスへ分かれていくことができます。
さらに、SuperSaiyanWarrior を土台にして、もう一段階細かいクラスを作ることもできます。
| 上位クラス | 下位クラス | 意味 |
|---|---|---|
| SaiyanWarrior | SuperSaiyanWarrior | スーパーサイヤ人の基本クラス |
| SuperSaiyanWarrior | GodSaiyanWarrior | 神流の覚醒戦士 |
| SuperSaiyanWarrior | BlueAuraWarrior | 青いオーラを持つ覚醒戦士 |
このように、親から子へ、さらにその子へとつながっていく構造が、クラスの階層です。

ドラゴンボール風にたとえると、サイヤ人戦士という大きな土台から、スーパーサイヤ人という特別な戦士が生まれ、さらに神流の覚醒戦士や青いオーラの戦士のように細かく分かれていく流れです。
サブクラスをさらに拡張すると何が起こるのか
サブクラスをさらに拡張した場合、新しく作ったクラスは、直前の親クラスだけでなく、さらに上のクラスの性質も受け継ぎます。
たとえば、次のような関係を考えます。
class SaiyanWarrior
{
}
class SuperSaiyanWarrior extends SaiyanWarrior
{
}
class GodSaiyanWarrior extends SuperSaiyanWarrior
{
}この場合、GodSaiyanWarrior は SuperSaiyanWarrior を継承しています。
そして、SuperSaiyanWarrior は SaiyanWarrior を継承しています。
つまり、GodSaiyanWarrior は次の要素を持つことになります。
| 受け継ぐもの | 内容 |
|---|---|
| GodSaiyanWarrior 自身の特徴 | 神流の覚醒戦士としての独自要素 |
| SuperSaiyanWarrior の特徴 | スーパーサイヤ人としての要素 |
| SaiyanWarrior の特徴 | サイヤ人戦士としての共通要素 |
| Object の特徴 | Javaオブジェクトとしての基本機能 |
継承は、直前の親だけで止まるわけではありません。
階層を上にたどって、親、その親、さらにその親の性質がつながっていきます。
ドラゴンボール風にたとえると、神流の覚醒戦士は、神流の覚醒戦士としての個性を持っています。
同時に、スーパーサイヤ人でもあり、サイヤ人戦士でもあり、Java上では Object につながるオブジェクトでもあります。
この「上の性質を積み重ねて持つ」という感覚が、クラス階層を理解するうえで大切です。
図:サイヤ人戦士クラスの階層

この図が示していること
この図では、SaiyanWarrior を土台にして、複数のサブクラスが作られる様子を表しています。
SaiyanWarrior の下には、SuperSaiyanWarrior、EliteSaiyanWarrior、SupportSaiyanWarrior があります。
さらに、SuperSaiyanWarrior の下には GodSaiyanWarrior や BlueAuraWarrior が続いています。
ここから分かるのは、Javaでは1つの親クラスから複数の子クラスを作れること、さらにサブクラスをもう一段階拡張できることです。
また、下位クラスは、直前の親クラスだけでなく、その上にあるクラスの性質も積み重ねて受け継ぐことが分かります。
Javaでは複数のスーパークラスを同時に継承できない
Javaでは、1つのクラスが複数のスーパークラスを同時に継承することはできません。
たとえば、次のような2つの親クラスがあるとします。
class SaiyanWarrior
{
}
class MedicalUnit
{
}この2つを同時に継承して、次のように書くことはできません。
// これはできない
class HealingWarrior extends SaiyanWarrior, MedicalUnit
{
}Javaのクラス継承では、直接の親クラスは1つだけです。
ドラゴンボール風にたとえると、1人の戦士クラスが「サイヤ人戦士の型」と「医療部隊の型」を、両方とも親クラスとして同時に持つような形は作れません。
なぜなら、複数の親クラスを同時に持つと、同じ名前のメソッドやフィールドがあった場合に、どちらを優先するのかが複雑になりやすいからです。
Javaはここをシンプルに保つため、クラスの継承は1本の親だけにしています。
| しくみ | Javaでの扱い |
|---|---|
| クラスの継承 | 親クラスは1つだけ |
| 複数の親クラスを同時に継承 | できない |
| サブクラスをさらに継承 | できる |
このルールを、単一継承と呼びます。
それでも共通の能力を増やしたいとき
Javaでは、クラスの継承で複数の親クラスを持つことはできません。
しかし、複数の能力や役割を持たせたい場合には、インターフェイスを使えます。
たとえば、ドラゴンボール風に考えると、戦士には次のような能力があります。
| 能力 | インターフェイス風の考え方 |
|---|---|
| 飛べる | Flyable |
| 気を使える | KiUser |
| 仲間を補助できる | Supporter |
| 任務を指揮できる | Leader |
クラスとしての親は1つだけでも、能力の約束は複数組み合わせられます。
class GodSaiyanWarrior extends SaiyanWarrior implements Flyable, KiUser, Leader
{
}このように考えると、次の違いが見えてきます。
| しくみ | できること |
|---|---|
| クラスの継承 | 親クラスは1つだけ |
| インターフェイス | 能力の約束を複数組み合わせられる |
今回の中心は Object クラスと継承ですが、Javaが「クラスの親は1つだけ」にしている一方で、「役割や能力はインターフェイスで複数持てる」ようにしていることも、あわせて覚えておくと整理しやすいです。
Object クラスはすべてのクラスの共通の親
ここからが今回の中心です。
Javaでは、クラスを宣言するときにスーパークラスを指定しない場合、そのクラスは自動的に Object クラスを親に持ちます。
たとえば、次のように書いたとします。
class SaiyanWarrior
{
}extends を書いていません。
しかし、考え方としては次のような関係になります。
class SaiyanWarrior extends Object
{
}つまり、何も書いていなくても、SaiyanWarrior は Object クラスの子クラスです。
このルールがあるため、Javaのクラスは最終的にすべて Object クラスにつながります。
| 書いたクラス | 実際の継承関係の考え方 |
|---|---|
| class SaiyanWarrior | SaiyanWarrior extends Object |
| class SuperSaiyanWarrior extends SaiyanWarrior | SuperSaiyanWarrior extends SaiyanWarrior extends Object |
| class GodSaiyanWarrior extends SuperSaiyanWarrior | GodSaiyanWarrior extends SuperSaiyanWarrior extends SaiyanWarrior extends Object |
Object クラスは、Javaのすべてのクラスにとっての一番上の親です。
ドラゴンボール風に考える Object クラス
ドラゴンボール風にたとえると、Object クラスは「すべての戦士や道具が、Javaの世界で共通に持っている最も基本の型」です。
サイヤ人戦士、スーパーサイヤ人戦士、スカウター、戦闘服、任務カードなど、いろいろなクラスを作れるとします。
それぞれ見た目も役割も違います。
| クラス | ドラゴンボール風の役割 |
|---|---|
| SaiyanWarrior | サイヤ人戦士 |
| SuperSaiyanWarrior | スーパーサイヤ人戦士 |
| Scouter | スカウター |
| BattleSuit | 戦闘服 |
| MissionCard | 任務カード |
しかし、Javaのクラスとしては、どれも最終的に Object につながります。
つまり Object クラスは、ドラゴンボール風に言えば、戦士や道具などの種類が分かれる前にある、Javaオブジェクトとしての共通土台のような存在です。
Object クラスにつながる階層の見方
Object クラスを一番上に置いて、クラスの階層を整理すると分かりやすくなります。
| 階層 | 例 |
|---|---|
| 最上位の共通の親 | Object |
| その子クラス | SaiyanWarrior |
| さらにその子クラス | SuperSaiyanWarrior |
| さらにその子クラス | GodSaiyanWarrior |
このような階層になっている場合、GodSaiyanWarrior は GodSaiyanWarrior 自身の特徴だけを持っているわけではありません。
次のように、上位クラスの性質も積み重ねています。
| クラス | 受け継ぐもの |
|---|---|
| Object | Javaオブジェクトとしての基本機能 |
| SaiyanWarrior | サイヤ人戦士としての共通機能 |
| SuperSaiyanWarrior | スーパーサイヤ人としての共通機能 |
| GodSaiyanWarrior | 神流の覚醒戦士としての独自機能 |
このように見ると、Javaの継承はバラバラの親子関係ではなく、Object を頂点にした大きな階層としてつながっていることが分かります。
図:Object クラスを頂点にした継承階層

この図が示していること
この図では、Object クラスが一番上にあり、その下に SaiyanWarrior や Scouter のようなクラスがつながっています。
SaiyanWarrior の下には SuperSaiyanWarrior、さらにその下に GodSaiyanWarrior が続いています。
この形から、下のクラスほど上のクラスの性質を積み重ねて受け継いでいることが分かります。
また、右下の注意カードでは、1つのクラスが複数のスーパークラスを同時に継承できないことも示しています。
つまりこの図は、次の2つを表しています。
| ポイント | 内容 |
|---|---|
| Object はすべてのクラスの共通の親 | 何も extends しないクラスも Object につながる |
| Javaのクラス継承は単一継承 | 1つのクラスが持てる直接の親クラスは1つだけ |
Javaのすべてのクラスは Object のメンバを持つ
Object クラスが共通の親であるということは、Javaのすべてのクラスが Object クラスのメンバを継承しているということです。
これはとても大事です。
なぜなら、Object クラスが持っている基本メソッドを、どんなクラスのオブジェクトでも使えるからです。
代表的なメソッドには、次のようなものがあります。
| メソッド | 役割 |
|---|---|
| equals(Object obj) | 引数のオブジェクトと同じかどうかを調べる |
| getClass() | オブジェクトのクラス情報を返す |
| toString() | オブジェクトを表す文字列を返す |
これらは、特定のクラスだけのものではありません。
Javaのあらゆるクラスが Object につながっているため、共通して使える基本メソッドです。
ドラゴンボール風に言うと、戦士、スカウター、任務カードなど、種類は違っても、Java世界のオブジェクトとして共通の基本動作を持っているということです。
equals の役割
equals は、あるオブジェクトが、引数として渡されたオブジェクトと同じかどうかを調べるためのメソッドです。
ドラゴンボール風にたとえると、「この戦士と、比較している戦士は同じ存在なのか」を確認するようなイメージです。
warrior1.equals(warrior2);このように使うと、warrior1 と warrior2 を比較できます。
ただし、equals の動きはクラスによってオーバーライドされることがあります。
何もオーバーライドしていない場合は、基本的には同じオブジェクトを指しているかどうかを見る考え方になります。
一方で、クラス側で equals を作り直せば、名前やIDなどをもとに「同じ戦士かどうか」を判断するようにもできます。
| 使い方 | 考え方 |
|---|---|
| Object 由来の equals | 同じオブジェクトかどうかを見る |
| オーバーライドした equals | クラスに合った同一性の判断をする |
ドラゴンボール風にたとえると、ただ同じ場所にいるかではなく、戦士番号や名前などをもとに同一人物か判断するように作り直せる、ということです。
getClass の役割
getClass は、そのオブジェクトがどのクラスに属しているかを返すメソッドです。
ドラゴンボール風にたとえると、「このオブジェクトは SaiyanWarrior なのか、SuperSaiyanWarrior なのか、GodSaiyanWarrior なのか」を確認するようなものです。
warrior1.getClass();このメソッドを使うと、変数の型ではなく、実際のオブジェクトのクラス情報を確認できます。
これは、ポリモーフィズムを学んだあとだと理解しやすいです。
たとえば、次のようなコードを考えます。
SaiyanWarrior warrior1 = new SuperSaiyanWarrior();この場合、変数の型は SaiyanWarrior です。
しかし、実体は SuperSaiyanWarrior です。
getClass() を使うと、実際のオブジェクトのクラス情報を確認できます。
| 見るもの | 内容 |
|---|---|
| 変数の型 | SaiyanWarrior |
| 実際のオブジェクト | SuperSaiyanWarrior |
| getClass() で分かるもの | 実体のクラス情報 |
ドラゴンボール風にたとえると、名簿上はサイヤ人戦士として扱っていても、実際にはスーパーサイヤ人戦士であることを確認できるような感覚です。
toString の役割
Object クラスのメソッドの中でも、特に大切なのが toString です。
toString は、オブジェクトを文字列として表したものを返すメソッドです。
たとえば、オブジェクトを System.out.println で表示するとき、内部では toString の結果が使われます。
System.out.println(warrior1);このように書いた場合、warrior1 の toString() が呼ばれ、その戻り値が表示されます。
つまり、toString は「そのオブジェクトを文字列でどう表すか」を決めるメソッドです。
ドラゴンボール風にたとえると、戦士が自分の情報を文字で名乗るための基本メソッドです。
Object から受け継いだ toString をそのまま使うとどうなるか
何も準備しないままオブジェクトを表示すると、Object クラスから受け継いだ toString がそのまま使われます。
その場合、次のような形式の文字列が表示されることがあります。
SaiyanWarrior@1a2b3cこれは Java としては正しい表示です。
ただし、人間にとってはあまり分かりやすくありません。
| 表示 | 分かること |
|---|---|
| SaiyanWarrior@1a2b3c | クラス名と識別用の情報らしきもの |
| 名前: 悟空、流派: 亀仙流 | オブジェクトの意味ある情報 |
ドラゴンボール風にたとえると、戦士を紹介してほしいのに、名前や流派ではなく、管理番号のようなものだけが表示される感覚です。
確認や学習には少し不便です。
toString をオーバーライドすると便利になる
そこで便利なのが、toString のオーバーライドです。
自分のクラスで toString を作り直すと、そのオブジェクトを表示したときに、意味のある文字列を返せるようになります。
たとえば、SaiyanWarrior クラスなら、次のようにできます。
class SaiyanWarrior
{
private String name;
private String styleName;
public SaiyanWarrior(String name, String styleName)
{
this.name = name;
this.styleName = styleName;
}
public String toString()
{
return "名前: " + name + "、流派: " + styleName;
}
}このように toString をオーバーライドしておくと、次のように表示できます。
SaiyanWarrior warrior1 = new SaiyanWarrior("悟空", "亀仙流");
System.out.println(warrior1);表示イメージは次のようになります。
名前: 悟空、流派: 亀仙流これは、Object から受け継いだ toString を、SaiyanWarrior クラスに合うように作り直している状態です。
ドラゴンボール風にたとえると、ただの管理番号ではなく、戦士が自分の名前や流派をきちんと名乗れるようにするイメージです。
toString はなぜ便利なのか
toString をオーバーライドすると、デバッグや表示がとても分かりやすくなります。
たとえば、オブジェクトの中身を確認したいときに、意味のある情報が表示されるからです。
| toString をそのまま使う場合 | toString をオーバーライドした場合 |
|---|---|
| SaiyanWarrior@1a2b3c のような表示 | 名前や流派など意味のある表示 |
| 中身が分かりにくい | 状態を確認しやすい |
| 学習中に混乱しやすい | オブジェクトの内容をつかみやすい |
toString は、Javaのクラスでとてもよく使うオーバーライド対象のひとつです。
図:Object の代表メソッドと toString のオーバーライド

この図が示していること
この図では、Object クラスが持つ代表的なメソッドと、toString をオーバーライドする意味を整理しています。
Object クラスには、equals、getClass、toString のような基本メソッドがあります。
すべてのクラスは Object につながっているため、こうしたメソッドを共通に持ちます。
右側では、SaiyanWarrior クラスが toString を自分用に作り直しています。
その結果、何も準備していない場合は SaiyanWarrior@1a2b3c のような表示になりやすいところを、名前や流派が分かる表示にできます。
この図から分かることは、Object のメソッドはただ受け継ぐだけでなく、必要に応じて自分のクラスらしくオーバーライドできるということです。
サンプルプログラムで Object と toString を確認する
ここでは、Object から受け継いだ toString を、SaiyanWarrior クラスでオーバーライドする例を見てみます。
class SaiyanWarrior
{
private String name;
private String styleName;
public SaiyanWarrior(String name, String styleName)
{
this.name = name;
this.styleName = styleName;
}
public String toString()
{
return "名前: " + name + "、流派: " + styleName;
}
}
class Main
{
public static void main(String[] args)
{
SaiyanWarrior warrior1 = new SaiyanWarrior("悟空", "亀仙流");
System.out.println(warrior1);
System.out.println(warrior1.getClass());
}
}このプログラムでは、SaiyanWarrior クラスに toString() を定義しています。
public String toString()
{
return "名前: " + name + "、流派: " + styleName;
}これは、Object から受け継いだ toString() を、SaiyanWarrior 用に作り直しているということです。
main メソッドでは、次のようにオブジェクトをそのまま表示しています。
System.out.println(warrior1);このとき、warrior1 の toString() が呼ばれます。
そのため、管理番号のような表示ではなく、名前と流派が分かる表示になります。
実行結果のイメージは次のようになります。
名前: 悟空、流派: 亀仙流
class SaiyanWarrior1行目では、toString() の戻り値が表示されています。
2行目では、getClass() によって実際のクラス情報が表示されています。
このように、Object 由来のメソッドは、Javaのどのクラスでも関係してきます。
なぜ Object クラスを知ることが大切なのか
Object クラスは、普段のコードで明示的に extends Object と書くことが少ないため、最初は少し地味に感じるかもしれません。
しかし、Javaの継承を理解するうえではとても重要です。
理由は、次のとおりです。
| 理由 | 内容 |
|---|---|
| すべてのクラスが Object につながる | Javaの継承階層の根になる |
| 基本メソッドを共通で持つ | equals、getClass、toString などが使える |
| オーバーライドの理解につながる | toString などを自分用に作り直せる |
| ポリモーフィズムの土台になる | Object 型でさまざまなオブジェクトを扱える考え方につながる |
Object クラスを知ると、Javaのクラスが完全にバラバラに存在しているのではなく、1つの大きな階層としてつながっていることが分かります。
Object 型でいろいろなオブジェクトを扱える
Object はすべてのクラスの親なので、Object 型の変数には、いろいろなクラスのオブジェクトを入れられます。
Object obj1 = new SaiyanWarrior("悟空", "亀仙流");
Object obj2 = new Scouter();
Object obj3 = new MissionCard();これは、SaiyanWarrior も Scouter も MissionCard も、すべて Object の一種だからです。
ドラゴンボール風にたとえると、戦士、スカウター、任務カードのように種類が違っても、Javaの世界ではすべて「オブジェクト」として扱えるということです。
ただし、Object 型として扱う場合、呼び出せるのは基本的に Object にあるメソッドです。
そのクラス独自のメソッドをそのまま呼びたい場合は、型を意識する必要があります。
この考え方は、スーパークラス型でサブクラスを扱うポリモーフィズムともつながります。
ドラゴンボール風に Object クラスを整理する
Javaのクラスは、見た目にはそれぞれ別の存在です。
ドラゴンボール風にたとえると、次のようにさまざまなクラスがあります。
| クラス | 役割 |
|---|---|
| SaiyanWarrior | サイヤ人戦士 |
| SuperSaiyanWarrior | スーパーサイヤ人戦士 |
| GodSaiyanWarrior | 神流の覚醒戦士 |
| Scouter | スカウター |
| MissionCard | 任務カード |
しかし、どれも最終的には Object クラスにつながっています。
そのため、どのクラスも Object 由来の基本メソッドを持っています。
| Object のメソッド | ドラゴンボール風のイメージ |
|---|---|
| equals | 同じ戦士や道具か確認する |
| getClass | 何のクラスの実体か調べる |
| toString | 自分の情報を文字で名乗る |
Object クラスは、すべてのクラスが最初に受け継いでいる共通の親です。
この考え方が分かると、Javaの継承は、単なる親子関係の集まりではなく、Object を頂点にしたひとつの大きな仕組みとして見えてきます。
この内容で押さえておきたいポイント
| ポイント | 内容 |
|---|---|
| クラスの階層 | 親から子へ、さらにその子へとつながる構造 |
| サブクラスの拡張 | 上位クラスのメンバも積み重ねて受け継ぐ |
| Javaの単一継承 | 1つのクラスが直接継承できる親クラスは1つだけ |
| Object クラス | すべてのクラスの共通の親 |
| extends を書かないクラス | 自動的に Object を親に持つ |
| equals | オブジェクト同士を比較する基本メソッド |
| getClass | 実際のクラス情報を確認するメソッド |
| toString | オブジェクトを文字列で表すメソッド |
| toString のオーバーライド | オブジェクトを分かりやすく表示できる |
Object クラスを理解すると、Javaのクラスがすべて共通の土台につながっていることが分かります。
そして、equals、getClass、toString のような基本メソッドが、どのクラスでも使える理由も見えてきます。
特に toString は、自分のクラスらしくオーバーライドすることで、オブジェクトの状態を分かりやすく表示できる便利なメソッドです。
