
Java超|Objectクラスと継承のしくみ
継承は便利ですが、親クラスを何本も同時に持てるわけではありません。Javaでは親クラスは1本だけ。その最上位には、すべてのクラスを支える Object クラスがあります。
Javaの継承では、親クラスから子クラスへ機能を受け継ぎながら、クラスを発展させていけます。
ドラゴンボールの世界観でたとえると、まず SaiyanWarrior というサイヤ人戦士の共通の型があります。そこから、SuperSaiyanWarrior、EliteSaiyanWarrior、SupportSaiyanWarrior のように、役割ごとのクラスを作っていくイメージです。
ただし、Javaの継承には大切なルールがあります。
それは、1つのクラスが同時に複数のスーパークラスを持つことはできないということです。
つまり、1つの子クラスが2つ以上の親クラスを同時に継承することはできません。
そして、もう1つ重要なルールがあります。
それが、スーパークラスを明示しないクラスは、自動的に Object クラスを親に持つという仕組みです。
このため、Javaのすべてのクラスは、最終的に Object クラスにつながっています。
Object クラスは、Javaにおけるすべてのクラスの共通の親です。
ドラゴンボール風にたとえると、サイヤ人戦士、スーパーサイヤ人戦士、スカウター、戦闘服、任務カードなど、さまざまなクラスがあっても、Javaの世界ではすべて Javaオブジェクトとしての共通土台を持っているということです。
この記事では、多重継承の制限、単一継承、インターフェイス、Object クラス、equals、getClass、toString について、ドラゴンボールの世界観で解説していきます。
Javaでは複数のスーパークラスを同時に継承できない
まず押さえておきたいのは、Javaでは1つのクラスが複数のスーパークラスを同時に継承できないという点です。
たとえば、次のような2つのクラスがあるとします。
class SaiyanWarrior
{
}
class MedicalUnit
{
}SaiyanWarrior はサイヤ人戦士を表すクラスです。
MedicalUnit は回復部隊を表すクラスです。
この2つを同時に親クラスとして持つクラスを作ることはできません。
// これはできない
class HealingWarrior extends SaiyanWarrior, MedicalUnit
{
}Javaでは、クラスの継承で指定できる親クラスは1つだけです。
| 書き方 | Javaで可能か |
|---|---|
| class SuperSaiyanWarrior extends SaiyanWarrior | 可能 |
| class HealingWarrior extends SaiyanWarrior, MedicalUnit | 不可能 |
ドラゴンボール風にたとえると、1人の戦士クラスが「サイヤ人戦士の型」と「回復部隊の型」を、同時に親として持つことはできないということです。
スーパーサイヤ人戦士は、サイヤ人戦士を土台にして作ることはできます。
しかし、サイヤ人戦士クラスと回復部隊クラスの両方を、親クラスとして同時に継承することはできません。
なぜ多重継承を制限しているのか
Javaがクラスの多重継承を許していない理由は、継承関係を分かりやすく保つためです。
もし1つのクラスが複数の親クラスを持てると、次のような問題が起こりやすくなります。
| 問題 | 内容 |
|---|---|
| 同じ名前のメソッドがある | どちらの親クラスのメソッドを使うのか迷う |
| 同じ名前のフィールドがある | どちらの値を参照するのか分かりにくい |
| 初期化の順番が複雑になる | どの親クラスから先に作るのか分かりにくい |
| 設計の見通しが悪くなる | クラスの責任範囲が曖昧になりやすい |
ドラゴンボール風にたとえると、1人の戦士が「亀仙流の師匠」と「医療部隊の師匠」を同時に親として持ち、両方から同じ名前の技を受け継いだら、どちらの技を優先するのか分かりにくくなります。
たとえば、両方の親クラスに train() があった場合、HealingWarrior が train() を呼び出したときに、どちらの train() を使うのかが問題になります。
Javaはこのような混乱を避けるため、クラスの親は1つだけにしています。
ただし、親から子へ、さらにその子へと縦につなげることはできます。
class SaiyanWarrior
{
}
class SuperSaiyanWarrior extends SaiyanWarrior
{
}
class GodSaiyanWarrior extends SuperSaiyanWarrior
{
}この場合、GodSaiyanWarrior は SuperSaiyanWarrior を継承し、SuperSaiyanWarrior は SaiyanWarrior を継承しています。
つまり、Javaでは複数の親を横に並べるのではなく、1本の系譜として縦につなげる形になります。
| しくみ | Javaでの扱い |
|---|---|
| クラスの直接の親 | 1つだけ |
| 複数の親クラスを同時に継承 | できない |
| 親から子、さらにその子へ継承 | できる |
図:Javaでは親クラスは1本だけ

この図が示していること
この図では、Javaのクラス継承では親クラスを1つだけ指定できることを表しています。
左側では、SaiyanWarrior から SuperSaiyanWarrior、さらに GodSaiyanWarrior へと縦につながる継承を示しています。
このように、親から子へ、さらにその子へと継承することはできます。
一方、右側では HealingWarrior が SaiyanWarrior と MedicalUnit の2つを同時に親にしようとしており、バツ印が付いています。
ここから分かるのは、Javaでは複数のスーパークラスを同時に継承できないということです。
Javaの継承は、複雑な網のように親を増やすのではなく、親クラスを1つに絞って分かりやすい系譜を作る仕組みです。
それでも複数の能力を持たせたいとき
クラスの多重継承はできません。
しかし、複数の能力や役割を持たせたい場面はあります。
そのときに使うのがインターフェイスです。
インターフェイスは、クラスの親そのものではなく、「この能力を持つ」という約束を表す仕組みです。
ドラゴンボール風にたとえると、戦士としての親クラスは1つでも、次のような能力の約束を複数持てるイメージです。
| 能力 | インターフェイス風の考え方 |
|---|---|
| 飛べる | Flyable |
| 気を使える | KiUser |
| 回復できる | Healer |
| 索敵できる | Sensor |
| 指揮できる | Leader |
たとえば、次のような形です。
class HealingWarrior extends SaiyanWarrior implements KiUser, Healer
{
}この場合、HealingWarrior は SaiyanWarrior を親クラスとして継承しています。
さらに、KiUser と Healer という能力の約束を持っています。
整理すると、次のようになります。
| しくみ | できること |
|---|---|
| クラスの継承 | 親クラスは1つだけ |
| インターフェイス | 複数の能力の約束を組み合わせられる |
つまり Java は、クラスの多重継承を避けつつ、必要な柔軟性はインターフェイスで補う仕組みを持っています。
ドラゴンボール風に言うと、戦士としての血筋や土台は1本にしながら、飛行能力、気の操作、回復能力、索敵能力などの「できること」は複数持たせられるということです。
スーパークラスを指定しないクラスはどうなるのか
ここからが、Object クラスの話です。
Javaでは、クラスを宣言するときにスーパークラスを指定しなかった場合、そのクラスは自動的に Object クラスを親に持ちます。
たとえば、次のように書いたとします。
class SaiyanWarrior
{
}このコードでは、extends を書いていません。
しかし、考え方としては次のような関係になります。
class SaiyanWarrior extends Object
{
}つまり、明示的に親クラスを書いていなくても、SaiyanWarrior は 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 |
このルールによって、Javaのすべてのクラスは最終的に Object クラスへつながります。
Object クラスはなぜすべてのクラスの共通の親なのか
Object クラスがすべてのクラスの共通の親と呼ばれる理由は、スーパークラスを明示しないクラスが自動的に Object を継承するからです。
ドラゴンボール風にたとえると、Object クラスは、戦士や道具などの種類が分かれる前にある、Javaオブジェクトとしての最も基本的な土台です。
たとえば、次のようなクラスがあるとします。
| クラス | ドラゴンボール風の役割 |
|---|---|
| SaiyanWarrior | サイヤ人戦士 |
| SuperSaiyanWarrior | スーパーサイヤ人戦士 |
| Scouter | スカウター |
| MissionCard | 任務カード |
| BattleSuit | 戦闘服 |
これらは見た目も役割も違います。
しかし、Javaのクラスとしては、どれも最終的に Object につながっています。
つまり、Object クラスは、すべてのクラスが共通して受け継ぐ、Java世界の最上位の親です。

継承の階層はどうつながっていくのか
Javaの継承関係は、上から下へと連なっていきます。
たとえば、次のような階層を考えます。
| 階層 | クラス例 | ドラゴンボール風のイメージ |
|---|---|---|
| 最上位 | Object | すべての共通土台 |
| その下 | SaiyanWarrior | サイヤ人戦士 |
| さらに下 | SuperSaiyanWarrior | スーパーサイヤ人戦士 |
| さらに下 | GodSaiyanWarrior | 神流の覚醒戦士 |
このとき、GodSaiyanWarrior は GodSaiyanWarrior 自身の特徴だけを持つわけではありません。
上の階層から、次のように受け継いでいます。
| 受け継ぐもの | 内容 |
|---|---|
| Object のメンバ | Javaオブジェクトとしての基本機能 |
| SaiyanWarrior のメンバ | サイヤ人戦士としての共通機能 |
| SuperSaiyanWarrior のメンバ | スーパーサイヤ人としての共通機能 |
| GodSaiyanWarrior のメンバ | 神流の覚醒戦士としての独自機能 |
つまり、下のクラスほど、上位クラスの性質を積み重ねながら、自分の個性を追加していく構造になります。
ドラゴンボール風にたとえると、神流の覚醒戦士は、神流の覚醒戦士であると同時に、スーパーサイヤ人戦士でもあり、サイヤ人戦士でもあり、Java上では Object につながるオブジェクトでもあるということです。
図:多重継承の制限とObjectクラスの関係

この図が示していること
この図では、Javaの継承が Object クラスを頂点にした階層としてつながる様子を表しています。
Object クラスの下に SaiyanWarrior があり、その下に SuperSaiyanWarrior、さらに GodSaiyanWarrior が続いています。
この構造から、Javaのクラスは最終的に Object クラスへつながることが分かります。
また、右上の注意カードでは、1つのクラスが2つの親クラスを同時に継承できないことを示しています。
一方で、右下では KiUser や Healer のようなインターフェイスを使えば、複数の能力の約束を組み合わせられることを示しています。
この図のポイントは次の2つです。
| ポイント | 内容 |
|---|---|
| Object クラス | すべてのクラスの共通の親 |
| 多重継承の制限 | クラスの親は1つだけ |
すべてのクラスは Object クラスのメンバを持つ
Object クラスが共通の親であるということは、Javaのすべてのクラスが Object クラスのメンバを継承しているということです。
そのため、どんなクラスのオブジェクトでも、Object クラス由来の基本メソッドを持っています。
代表的なメソッドは次の3つです。
| メソッド | 機能 |
|---|---|
| equals(Object obj) | オブジェクトが引数と同じものかどうかを調べる |
| getClass() | オブジェクトのクラスを返す |
| toString() | オブジェクトを表す文字列を返す |
これらは、特定のクラスだけに用意されている特別なメソッドではありません。
SaiyanWarrior、SuperSaiyanWarrior、Scouter、MissionCard のように、どんなクラスでも最終的に Object につながるため、共通して使える基本機能です。
equals は何をするメソッドなのか
equals は、あるオブジェクトと、引数で渡したオブジェクトが同じものかどうかを調べるメソッドです。
たとえば、次のように使います。
warrior1.equals(warrior2);ドラゴンボール風にたとえると、今見ている戦士と、比べようとしている戦士が同じ存在かどうかを確認するようなイメージです。
ただし、equals の意味はクラスによって作り直されることがあります。
Object 由来の equals は、基本的には同じオブジェクトを指しているかどうかを見る考え方です。
一方で、クラス側で equals をオーバーライドすれば、戦士番号や名前をもとに「同じ戦士かどうか」を判断するようにもできます。
| equals の使い方 | 内容 |
|---|---|
| Object 由来の equals | 同じオブジェクトかどうかを見る |
| オーバーライドした equals | クラスに合った同一性の判断をする |
ドラゴンボール風に言うと、単に同じ実体を見ているかだけでなく、戦士IDや名前などを基準にして、同じ登録戦士かどうかを判断するように作り直せるということです。
getClass は何をするメソッドなのか
getClass は、そのオブジェクトがどのクラスに属しているかを返すメソッドです。
たとえば、次のように使います。
warrior1.getClass();ドラゴンボール風にたとえると、この戦士は SaiyanWarrior なのか、SuperSaiyanWarrior なのか、GodSaiyanWarrior なのかを確認するような感覚です。
これは、ポリモーフィズムを考えるときにも大切です。
たとえば、次のように書いたとします。
SaiyanWarrior warrior1 = new SuperSaiyanWarrior();この場合、変数の型は SaiyanWarrior です。
しかし、実際のオブジェクトは SuperSaiyanWarrior です。
| 見るもの | 内容 |
|---|---|
| 変数の型 | SaiyanWarrior |
| 実際のオブジェクト | SuperSaiyanWarrior |
| getClass() で分かるもの | 実体のクラス情報 |
getClass を使うと、見た目の変数型ではなく、実際のオブジェクトのクラス情報を確認できます。
ドラゴンボール風にたとえると、名簿上はサイヤ人戦士として扱っていても、スカウターで実体を調べるとスーパーサイヤ人戦士だと分かるようなイメージです。
toString は何をするメソッドなのか
toString は、オブジェクトを文字列で表したものを返すメソッドです。
そして、オブジェクトをそのまま出力しようとしたとき、この toString が呼び出されます。
たとえば、次のように書いたとします。
System.out.println(warrior1);このとき、内部的には warrior1 の toString() の結果が表示されます。
つまり toString は、そのオブジェクトを文字でどう表すかを決めるメソッドです。
ドラゴンボール風にたとえると、戦士が自分の情報を文字で名乗るための基本メソッドです。
何も準備しないと Object クラスの toString が使われる
自分のクラスで toString を用意しなかった場合、Object クラスから継承した toString がそのまま使われます。
その場合、次のような形式の文字列が表示されることがあります。
SaiyanWarrior@1a2b3cこれはJavaとしては正しい表示です。
しかし、人間にとっては少し分かりにくいです。
| 表示 | 印象 |
|---|---|
| SaiyanWarrior@1a2b3c | 機械的な識別表示 |
| 名前: 悟空、流派: 亀仙流 | 意味が分かりやすい表示 |
ドラゴンボール風にたとえると、戦士の紹介をしてほしいのに、名前や流派ではなく、識別番号だけが出てくるような感覚です。
このままでは、確認やデバッグには少し不便です。
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 の代表メソッドと共通機能

この図が示していること
この図では、Object クラスが持つ代表的なメソッドを整理しています。
Object クラスには、equals、getClass、toString のような基本メソッドがあります。
すべてのクラスは Object につながっているため、こうしたメソッドを共通して持ちます。
また、toString は自分のクラスでオーバーライドすると、分かりやすい文字列を返せるようになります。
| 状態 | 表示例 |
|---|---|
| Object 由来の toString をそのまま使う | SaiyanWarrior@1a2b3c |
| toString をオーバーライドする | 名前: 悟空、流派: 亀仙流 |
この図から分かることは、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 SuperSaiyanWarrior extends SaiyanWarrior
{
public SuperSaiyanWarrior(String name, String styleName)
{
super(name, styleName);
}
}
class Main
{
public static void main(String[] args)
{
SaiyanWarrior warrior1 = new SaiyanWarrior("天津飯", "鶴仙流");
SaiyanWarrior warrior2 = new SuperSaiyanWarrior("悟空", "亀仙流");
System.out.println(warrior1);
System.out.println(warrior2);
System.out.println(warrior1.getClass());
System.out.println(warrior2.getClass());
System.out.println(warrior1.equals(warrior2));
}
}このプログラムでは、SaiyanWarrior クラスに toString() を定義しています。
public String toString()
{
return "名前: " + name + "、流派: " + styleName;
}これは、Object から受け継いだ toString() を、SaiyanWarrior 用に作り直しているということです。
main メソッドでは、次のようにオブジェクトをそのまま表示しています。
System.out.println(warrior1);
System.out.println(warrior2);このとき、それぞれの toString() が呼ばれます。
実行結果のイメージは次のようになります。
名前: 天津飯、流派: 鶴仙流
名前: 悟空、流派: 亀仙流
class SaiyanWarrior
class SuperSaiyanWarrior
false1行目と2行目では、toString() の戻り値が表示されています。
3行目と4行目では、getClass() によって実際のクラス情報が表示されています。
warrior2 の変数の型は SaiyanWarrior ですが、実体は SuperSaiyanWarrior です。
そのため、getClass() では SuperSaiyanWarrior の情報が表示されます。
最後の false は、warrior1 と warrior2 が同じオブジェクトではないことを表しています。
このように、Object 由来のメソッドは、Javaのどのクラスでも関係してきます。
Object クラスを知ると継承の全体像が見える
Object クラスは、Javaの継承全体を支える土台です。
Object クラスを理解すると、次の流れが見えてきます。
| 流れ | 内容 |
|---|---|
| Javaのクラス継承は親クラス1つだけ | 多重継承はできない |
| 親をたどると最終的に Object に行き着く | すべてのクラスの共通の親 |
| すべてのクラスは Object の基本メソッドを持つ | equals、getClass、toString など |
| 必要に応じて基本メソッドを作り直せる | toString などをオーバーライドできる |
この見方ができると、Javaの継承はバラバラの親子関係ではなく、Object を最上位にした一本の大きな系譜として理解できます。
ドラゴンボール風にたとえると、戦士ごとに個性は違います。
サイヤ人戦士、スーパーサイヤ人戦士、神流の覚醒戦士、スカウター、戦闘服、任務カードなど、クラスの種類も違います。
それでもJavaの世界では、すべてが Object という共通の土台につながっています。
ドラゴンボール風に多重継承と Object クラスを整理する
Javaのクラスは、いろいろな戦士や道具の型のようなものです。
たとえば、次のようなクラスがあります。
| クラス | ドラゴンボール風のイメージ |
|---|---|
| SaiyanWarrior | サイヤ人戦士 |
| SuperSaiyanWarrior | スーパーサイヤ人戦士 |
| GodSaiyanWarrior | 神流の覚醒戦士 |
| Scouter | スカウター |
| MissionCard | 任務カード |
ただし、1つのクラスが複数の親クラスを同時に持つことはできません。
親クラスは1本だけです。
その一方で、どんなクラスも上までたどれば Object クラスに行き着きます。
だから、どのクラスも次の基本機能を共通に持っています。
| Object のメソッド | ドラゴンボール風のイメージ |
|---|---|
| equals | 同じ戦士や道具か確認する |
| getClass | 実際の型を確認する |
| toString | 自分の情報を文字で名乗る |
つまり、Javaの継承は、親クラスは1本だけでつながり、その最上位には Object があるという構造です。
この内容で押さえておきたいポイント
| ポイント | 内容 |
|---|---|
| 多重継承 | Javaでは1つのクラスが複数のスーパークラスを同時に継承できない |
| 単一継承 | クラスの直接の親は1つだけ |
| 継承階層 | 親から子へ、さらにその子へと縦につながる |
| インターフェイス | 複数の能力の約束を組み合わせられる |
| Object クラス | すべてのクラスの共通の親 |
| extends を書かないクラス | 自動的に Object を親に持つ |
| equals | オブジェクト同士を比較する |
| getClass | 実際のクラス情報を返す |
| toString | オブジェクトを文字列で表す |
多重継承の制限を知ると、Javaがクラスの親子関係をシンプルに保っていることが分かります。
そして Object クラスを知ると、Javaのすべてのクラスが共通の土台につながっていることが見えてきます。
この2つを合わせて理解すると、Javaの継承は「自由に枝分かれする複雑な網」ではなく、Object を頂点とした一本の系譜として整理できます。
