- 1 1. 継承と super の関係
- 2 2. super の使い方(3つの基本パターン)
- 3 3. 実践サンプルコードで理解する super
- 4 4. this と super の違い
- 4.1 4.1 this は「自分自身(このインスタンス)」を指す
- 4.2 4.2 super は「親クラス側」を指す
- 4.3 4.3 違いを一言でまとめるとこうなる
- 4.4 4.4 this と super の使い分け(よくある3パターン)
- 4.5 4.5 フィールド参照の違い(同名フィールドがある場合)
- 4.6 4.6 メソッド呼び出しの違い(オーバーライド時に分かりやすい)
- 4.7 4.7 コンストラクタ呼び出しの違い(this() と super())
- 4.8 4.8 this() と super() は同時に使えない(初心者がよく詰まる)
- 4.9 4.9 よくある混乱:「thisは子、superは親」だけでOK?
- 4.10 4.10 このセクションのまとめ
- 5 5. よくある間違い・注意点(エラー回避のコツ)
- 5.1 5.1 super() を書く位置が間違っている(コンストラクタの先頭ルール)
- 5.2 5.2 親に引数なしコンストラクタがないのに super() を省略してしまう
- 5.3 5.3 super() と this() を同時に使おうとしてしまう
- 5.4 5.4 staticメソッドの中で super を使おうとしてしまう
- 5.5 5.5 super を「親のインスタンスを作るもの」と勘違いする
- 5.6 5.6 フィールドの同名は避ける(super.field が必要になる設計自体が危険)
- 5.7 5.7 super.method() を使えば必ず親の処理が動く…とは限らない?
- 5.8 5.8 このセクションのまとめ(失敗しないためのチェックリスト)
- 6 6. まとめ(要点整理)
- 7 7. FAQ(よくある質問)
- 7.1 7.1 super はどんなときに使うべきですか?
- 7.2 7.2 super() を書かないとどうなりますか?
- 7.3 7.3 super() と this() は何が違いますか?
- 7.4 7.4 コンストラクタ内で super() と this() を両方呼べますか?
- 7.5 7.5 super は static メソッド内で使えますか?
- 7.6 7.6 super を使うと親クラスのインスタンスが別に生成されますか?
- 7.7 7.7 super.method() と書けば必ず親の処理だけが動きますか?
- 7.8 7.8 super.field は積極的に使うべきですか?
- 7.9 7.9 super はインターフェースでも使えますか?
- 7.10 7.10 super を使いこなすコツはありますか?
1. 継承と super の関係
Javaの super を理解するためには、まず 「継承(inheritance)」 の仕組みを押さえるのが近道です。super は単体で覚えるよりも、「親クラスと子クラスの関係の中で、何を参照しているのか」を理解すると一気に分かりやすくなります。
このセクションでは、super が必要になる背景を、初心者向けに丁寧に説明します。
1.1 Javaの継承とは?(extends の基本)
Javaでは、あるクラスをベースにして別のクラスを作ることができます。これを 継承 と呼びます。
- 親クラス(スーパークラス):元になるクラス
- 子クラス(サブクラス):親クラスを引き継いで作るクラス
継承を使うと、親クラスが持っている機能(フィールドやメソッド)を、子クラスがそのまま利用できます。
継承の基本形(extends)
class Parent {
void hello() {
System.out.println("Hello from Parent");
}
}
class Child extends Parent {
}この例では、Child は Parent を継承しているため、Child のインスタンスからも hello() を呼べます。
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.hello(); // 親クラスのメソッドを呼べる
}
}実行結果:
Hello from Parentこのように、子クラスは親クラスの機能を「引き継ぐ」ことができます。
1.2 なぜ super が必要なのか?
「継承しているなら、親の機能はそのまま使えるんでしょ?」と思うかもしれません。
実際、多くのケースでは super を書かなくても困りません。
しかし、次のような状況になると super が必要になります。
- 子クラスで 親クラスのメソッドを上書き(オーバーライド) したい
- 親と子で 同じ名前のフィールド を持ってしまった
- 子クラスのコンストラクタから 親のコンストラクタを明示的に呼びたい
つまり super は、簡単に言うとこういう役割です。
「親クラス側のメンバーを明示的に呼びたいときに使う」
1.3 オーバーライドと super の関係(親の処理も使いたい)
Javaでは、子クラス側で親クラスのメソッドを作り直すことができます。
これを オーバーライド(override) と呼びます。
オーバーライドの例
class Parent {
void greet() {
System.out.println("Parent: Hello!");
}
}
class Child extends Parent {
@Override
void greet() {
System.out.println("Child: Hi!");
}
}この場合、Child の greet() は親の greet() を上書きしているので、子の処理が優先されます。
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.greet();
}
}実行結果:
Child: Hi!ここで「子の処理を追加したいけど、親の処理も残したい」というケースが出てきます。
そのときに登場するのが super です。
super.greet() で親のメソッドを呼ぶ
class Parent {
void greet() {
System.out.println("Parent: Hello!");
}
}
class Child extends Parent {
@Override
void greet() {
super.greet(); // 親の処理も呼ぶ
System.out.println("Child: Hi!");
}
}実行結果:
Parent: Hello!
Child: Hi!このように、super を使うと 親のメソッドを明示的に呼び出して、処理を組み合わせる ことができます。
1.4 親と子で同じ名前のフィールドがあるとき(super がないと混乱する)
フィールド(変数)についても、親と子で同じ名前を使ってしまうケースがあります。
例えば、次のようなコードです。
class Parent {
int value = 100;
}
class Child extends Parent {
int value = 200;
void printValue() {
System.out.println(value);
}
}この場合、printValue() の value は 子クラスの value(200) を指します。
実行すると:
200「親の value(100)も表示したい」という場合に super.value を使います。
class Child extends Parent {
int value = 200;
void printValue() {
System.out.println(value); // 子クラスの value
System.out.println(super.value); // 親クラスの value
}
}実行結果:
200
100ポイントは次の通りです。
value→ 子クラス側super.value→ 親クラス側
このように、super は「どちらを参照しているか」をはっきりさせるためにも使われます。
1.5 super は「親クラスの参照」を表すキーワード
ここまでを整理すると、super は次のような意味を持っています。
superは 親クラスを指す参照- 子クラスの中から 親クラスのメンバーにアクセスするためのキーワード
- 「親の処理も使いたい」「親の値を参照したい」というときに役立つ
初心者のうちは、まずこの1行で覚えるのが一番ラクです。
superは 親クラス版のメソッドやフィールドを呼ぶためのキーワード
2. super の使い方(3つの基本パターン)
super は「親クラスを参照するキーワード」でした。
では実際に、Javaで super はどんな場面で使われるのでしょうか?
結論として、使い方は大きく 次の3パターン に整理できます。
- 親クラスの コンストラクタ を呼び出す(
super()) - 親クラスの メソッド を呼び出す(
super.method()) - 親クラスの フィールド を参照する(
super.field)
このセクションでは、初心者がつまずきやすいポイントも含めて、順番に丁寧に解説します。
2.1 親クラスのコンストラクタを呼び出す(super() / super(引数))
2.1.1 コンストラクタとは何か(超ざっくり復習)
コンストラクタは、クラスのインスタンス(オブジェクト)を作るときに実行される特別な処理です。
class Person {
Person() {
System.out.println("Personのコンストラクタ");
}
}このように、クラス名と同じ名前で定義されます。
2.1.2 継承では「親のコンストラクタ → 子のコンストラクタ」の順で動く
Javaの継承では、子クラスのインスタンスを作るときでも、内部的にはまず親クラスの初期化が必要になります。
そのため、子クラスのコンストラクタが動く前に、親クラスのコンストラクタが呼ばれる というルールがあります。
例を見てみましょう。
class Parent {
Parent() {
System.out.println("親コンストラクタ");
}
}
class Child extends Parent {
Child() {
System.out.println("子コンストラクタ");
}
}実行:
public class Main {
public static void main(String[] args) {
Child c = new Child();
}
}出力:
親コンストラクタ
子コンストラクタここで注目すべき点は、Child() の中に super() が書かれていないのに、親コンストラクタが呼ばれていることです。
2.1.3 super() は書かなくても呼ばれる(ただし条件あり)
実は、子クラスのコンストラクタの先頭には、Javaが自動的に次の1行を挿入します。
super();つまり、以下の2つはほぼ同じ意味になります。
Child() {
System.out.println("子コンストラクタ");
}
Child() {
super(); // コンパイラが暗黙で入れる
System.out.println("子コンストラクタ");
}ただし、これが成立するのは 親クラスに引数なしコンストラクタが存在する場合 です。
2.1.4 親クラスが「引数ありコンストラクタ」しか持たない場合は要注意
初心者がよくハマるのがこのパターンです。
class Parent {
Parent(int x) {
System.out.println("親: " + x);
}
}
class Child extends Parent {
Child() {
System.out.println("子");
}
}これをコンパイルするとエラーになります。
理由は、子クラス側で super()(引数なし)を暗黙に呼ぼうとするのに、親に引数なしコンストラクタが存在しないからです。
この場合は、子クラスで 明示的に super(引数) を書く必要があります。
class Child extends Parent {
Child() {
super(10); // 親の引数ありコンストラクタを呼ぶ
System.out.println("子");
}
}出力:
親: 10
子2.1.5 super(...) は必ずコンストラクタの先頭に書く
コンストラクタ内で super(...) を使う場合、ルールがあります。
super(...)は コンストラクタの1行目 に書かなければならない
例えば次はエラーになります。
Child() {
System.out.println("先に何か処理");
super(10); // エラー
}親の初期化が終わっていないのに子の処理を始めるのは危険なので、Javaはこれを禁止しています。
2.2 親クラスのメソッドを呼び出す(super.method())
次に多いのが「オーバーライドしたけど親の処理も使いたい」ケースです。
2.2.1 super.method() の基本
class Parent {
void show() {
System.out.println("親のshow");
}
}
class Child extends Parent {
@Override
void show() {
System.out.println("子のshow");
}
void test() {
super.show(); // 親のメソッドを呼ぶ
show(); // 自分のメソッドを呼ぶ
}
}実行:
public class Main {
public static void main(String[] args) {
Child c = new Child();
c.test();
}
}出力:
親のshow
子のshow2.2.2 どういうときに便利?
super.method() が便利な場面は、例えば次のようなケースです。
- 親クラスの処理が「共通の前処理」になっている
- 子クラスで追加処理だけ足したい
- ログ出力や入力チェックなどを親でまとめている
例:親の処理を活かしつつ、子で追加する
class Parent {
void process() {
System.out.println("共通処理");
}
}
class Child extends Parent {
@Override
void process() {
super.process(); // 共通処理を再利用
System.out.println("子独自の処理");
}
}こうしておくと、共通処理を親に集約できて、保守しやすくなります。
2.3 親クラスのフィールドを参照する(super.field)
フィールド(メンバー変数)でも、親と子で同じ名前を使ってしまうことがあります。
このとき super.field を使うと、親の値を明示できます。
2.3.1 フィールド名がかぶった場合の例
class Parent {
int value = 100;
}
class Child extends Parent {
int value = 200;
void print() {
System.out.println(value); // 子のvalue
System.out.println(super.value); // 親のvalue
}
}出力:
200
1002.3.2 そもそもフィールド名をかぶせるべき?
実務的には、フィールド名を親子で同じにする設計は 混乱の元 になりやすいです。
ただ、次のような事情で「どうしても同名になる」ことがあります。
- 既存コードがそうなっていて変更できない
- ライブラリの親クラス仕様に合わせる必要がある
- 意図的に「親と別の値」を持たせたい(おすすめはしない)
そのような場面で super.field が役に立ちます。
2.4 このセクションのまとめ(使い方3パターン)
super の使い方は、次の3つに整理できます。
super()/super(引数)
→ 親コンストラクタを呼ぶsuper.method()
→ 親メソッドを呼ぶ(オーバーライド時に便利)super.field
→ 親フィールドを参照する(同名衝突時)
3. 実践サンプルコードで理解する super
ここまでで、super の役割と使い方(3パターン)が分かりました。
- 親のコンストラクタを呼ぶ
super() - 親のメソッドを呼ぶ
super.method() - 親のフィールドを参照する
super.field
ただ、初心者のうちは「理屈は分かったけど、実際どんな順番で動くの?」となりがちです。
このセクションでは、動作がイメージしやすいサンプルコード を順番に見ていきます。
3.1 例1:super() によるコンストラクタ呼び出し(親→子の順)
まずは一番基本の「親コンストラクタが先に動く」パターンです。
class Parent {
Parent() {
System.out.println("Parent constructor");
}
}
class Child extends Parent {
Child() {
super(); // 明示してもOK(省略も可能)
System.out.println("Child constructor");
}
}
public class Main {
public static void main(String[] args) {
new Child();
}
}出力:
Parent constructor
Child constructorポイント
- 子クラスのインスタンスを作るときでも、必ず 親の初期化が先
super()は省略できるが、書いておくと意図が明確になる場合もある
3.2 例2:親が引数ありコンストラクタしか持たない場合(super(引数) 必須)
次に、実務でも遭遇しやすい「親に引数なしコンストラクタがない」ケースです。
class Parent {
Parent(String name) {
System.out.println("Parent: " + name);
}
}
class Child extends Parent {
Child() {
super("Taro"); // 親に引数が必要なので明示する
System.out.println("Child created");
}
}
public class Main {
public static void main(String[] args) {
new Child();
}
}出力:
Parent: Taro
Child createdポイント
- 親クラスが
Parent()を持たない場合、子でsuper(...)を必ず書く - これを忘れるとコンパイルエラーになる
3.3 例3:super.method() で親メソッドを呼ぶ(オーバーライド+追加処理)
次は、継承で一番「使いどころが分かりやすい」パターンです。
class Parent {
void greet() {
System.out.println("Hello from Parent");
}
}
class Child extends Parent {
@Override
void greet() {
super.greet(); // 親の処理を呼ぶ
System.out.println("Hello from Child");
}
}
public class Main {
public static void main(String[] args) {
new Child().greet();
}
}出力:
Hello from Parent
Hello from Childポイント
- 親の処理を「消さずに再利用」できる
- 子で処理を追加するだけなら、親のコードをコピペしなくて済む
3.4 例4:super.field で親フィールドを参照する(同名フィールドがある場合)
親と子で同じ名前のフィールドがあると、通常は 子のフィールドが優先 されます。
このとき super.field で親側を参照できます。
class Parent {
int value = 100;
}
class Child extends Parent {
int value = 200;
void printValues() {
System.out.println("Child value: " + value);
System.out.println("Parent value: " + super.value);
}
}
public class Main {
public static void main(String[] args) {
new Child().printValues();
}
}出力:
Child value: 200
Parent value: 100ポイント
valueは子クラス側super.valueは親クラス側
3.5 例5:親メソッド+子メソッドを「両方」呼び分ける
初心者が混乱しやすいのは、「今どっちのメソッドが呼ばれているの?」という点です。
そこで、意図的に親と子を呼び分ける例を見てみましょう。
class Parent {
void show() {
System.out.println("Parent show()");
}
}
class Child extends Parent {
@Override
void show() {
System.out.println("Child show()");
}
void test() {
super.show(); // 親の show()
this.show(); // 子の show()(thisは省略しても同じ)
}
}
public class Main {
public static void main(String[] args) {
new Child().test();
}
}出力:
Parent show()
Child show()ポイント
super.show()→ 親のメソッドthis.show()→ 子のメソッド(通常のshow()と同じ)
3.6 実務でありがちな例:親の共通処理を使ってログを統一する
最後に「実務っぽい例」も出しておきます。
親で共通処理(ログなど)を持たせておくと、子クラス側で統一がしやすいです。
class BaseService {
void execute() {
System.out.println("[LOG] start");
}
}
class UserService extends BaseService {
@Override
void execute() {
super.execute(); // 共通ログを再利用
System.out.println("UserService logic");
}
}
public class Main {
public static void main(String[] args) {
new UserService().execute();
}
}出力:
[LOG] start
UserService logicポイント
- 共通処理を親にまとめておける
- 子は必要な部分だけ追加すればよい
3.7 このセクションのまとめ
このセクションで押さえるべきことは次の通りです。
- コンストラクタは親→子の順で動く
- 親に引数ありコンストラクタしかないなら
super(引数)が必須 super.method()を使うと 親の処理を活かしつつ拡張できるsuper.fieldは 同名フィールドの衝突回避に使える
4. this と super の違い
Javaの super を学んでいると、ほぼ必ずセットで出てくるのが this です。
どちらも「何かを参照している」キーワードなので、初心者のうちは混乱しやすいポイントでもあります。
このセクションでは、this と super の違いを 定義 → 使い分け → 実例 の順で整理します。
4.1 this は「自分自身(このインスタンス)」を指す
this は、現在のオブジェクト(インスタンス)そのものを指すキーワードです。
this= 今動いているオブジェクト自身
たとえば、フィールドと引数の名前が同じ場合に、区別するためによく使います。
class User {
String name;
User(String name) {
this.name = name; // フィールドnameに代入
}
}この例での this.name は「このインスタンスが持っているフィールドname」を意味します。
4.2 super は「親クラス側」を指す
super は、親クラス(スーパークラス)を参照するキーワードです。
super= 親クラス側のメンバーを明示的に呼ぶための参照
つまり super は、継承している状況でのみ意味を持ちます。
4.3 違いを一言でまとめるとこうなる
初心者向けに、まずはこの1行で覚えるのが一番早いです。
this→ 自分(子クラス側)super→ 親(親クラス側)
4.4 this と super の使い分け(よくある3パターン)
this と super は、主に次の場面で登場します。
- フィールド参照(
this.field/super.field) - メソッド呼び出し(
this.method()/super.method()) - コンストラクタ呼び出し(
this()/super())
順番に見ていきます。

4.5 フィールド参照の違い(同名フィールドがある場合)
親と子で同じ名前のフィールドがあるとき、参照先が分かれます。
class Parent {
int value = 100;
}
class Child extends Parent {
int value = 200;
void print() {
System.out.println(this.value); // 子のvalue
System.out.println(super.value); // 親のvalue
}
}
public class Main {
public static void main(String[] args) {
new Child().print();
}
}出力:
200
100ポイント
this.valueは「子クラスのフィールド」super.valueは「親クラスのフィールド」
ちなみに、this は省略できるため value と書いた場合も this.value と同じ意味になります。
4.6 メソッド呼び出しの違い(オーバーライド時に分かりやすい)
次はメソッドです。親と子で同じメソッド名がある場合、通常は子が優先されます(オーバーライド)。
class Parent {
void show() {
System.out.println("Parent show()");
}
}
class Child extends Parent {
@Override
void show() {
System.out.println("Child show()");
}
void test() {
this.show(); // 子のshow()(省略してもOK)
super.show(); // 親のshow()
}
}
public class Main {
public static void main(String[] args) {
new Child().test();
}
}出力:
Child show()
Parent show()ポイント
this.show()→ 子のメソッド(通常のshow()と同じ)super.show()→ 親のメソッド
4.7 コンストラクタ呼び出しの違い(this() と super())
ここは少しややこしいですが、超重要です。
this()は 同じクラス内の別コンストラクタ を呼ぶsuper()は 親クラスのコンストラクタ を呼ぶ
4.7.1 this() の例(コンストラクタをまとめる)
class User {
String name;
int age;
User() {
this("NoName", 0); // 引数ありコンストラクタへ
}
User(String name, int age) {
this.name = name;
this.age = age;
}
}このように、コンストラクタの処理を1つに集約できるので、重複を減らせます。
4.7.2 super() の例(親を初期化する)
class Parent {
Parent() {
System.out.println("Parent constructor");
}
}
class Child extends Parent {
Child() {
super(); // 親を初期化
System.out.println("Child constructor");
}
}出力:
Parent constructor
Child constructor4.8 this() と super() は同時に使えない(初心者がよく詰まる)
コンストラクタ内で次のように書きたくなる人が多いです。
Child() {
this(1);
super(); // これも呼びたい
}しかしこれは 不可能 です。
理由は、this() も super() も コンストラクタの1行目にしか書けない からです。
1行目に書けるのは
this()かsuper()のどちらか片方だけ
4.9 よくある混乱:「thisは子、superは親」だけでOK?
基本はそれでOKです。
ただし、もう1段だけ正確に言うとこうなります。
thisは 実体としては同じオブジェクト を指しているsuperは 親クラスの領域(親として見たときの参照) を明示している
つまり super は「別オブジェクトを作る」わけではありません。
同じインスタンスを、親クラスの視点で扱っている イメージです。
4.10 このセクションのまとめ
thisは 自分自身(このインスタンス)superは 親クラス側のメンバー参照- フィールド・メソッドは
thisとsuperで呼び分けられる - コンストラクタは
this()とsuper()があり、同時に使えない
5. よくある間違い・注意点(エラー回避のコツ)
super は便利ですが、使い方を間違えるとコンパイルエラーになったり、意図しない挙動になったりします。
特に初心者のうちは「何がダメなのか分からない」状態に陥りやすいので、このセクションで よくあるミス を先に潰しておきましょう。
5.1 super() を書く位置が間違っている(コンストラクタの先頭ルール)
super() や super(引数) は、コンストラクタの1行目 に書く必要があります。
NG例(エラーになる)
class Parent {
Parent(int x) {}
}
class Child extends Parent {
Child() {
System.out.println("先に処理したい");
super(10); // エラー:1行目ではない
}
}OK例(正しい)
class Child extends Parent {
Child() {
super(10); // 1行目に書く
System.out.println("子の処理");
}
}親の初期化が終わる前に子の処理を始めるのは危険なので、Javaがルールで禁止しています。
5.2 親に引数なしコンストラクタがないのに super() を省略してしまう
親クラスに 引数ありコンストラクタしか存在しない 場合、子クラスは super(引数) を書かないとエラーになります。
親が引数ありコンストラクタしかない例
class Parent {
Parent(String name) {}
}
class Child extends Parent {
Child() {
// super() が暗黙に入るが、Parent() が存在しないのでエラー
}
}この場合は、子で明示的に書きます。
class Child extends Parent {
Child() {
super("Taro");
}
}5.3 super() と this() を同時に使おうとしてしまう
コンストラクタの中で、次のように「両方呼びたい」と思うことがあります。
this()で同じクラスの別コンストラクタへsuper()で親のコンストラクタへ
しかし、これはできません。
NG例(エラーになる)
class Parent {
Parent() {}
}
class Child extends Parent {
Child() {
this(1);
super(); // エラー:super() は書けない
}
Child(int x) {}
}理由:
this()もsuper()も 1行目にしか書けない- 1行目に置けるのはどちらか片方だけ
5.4 staticメソッドの中で super を使おうとしてしまう
super は、親クラスの インスタンスメンバー を参照するための仕組みです。
そのため、staticメソッド(クラスに属するメソッド)では基本的に使えません。
NG例(イメージ)
class Parent {
void hello() {}
}
class Child extends Parent {
static void test() {
super.hello(); // エラー(staticの中でsuperは使えない)
}
}ポイント:
- staticメソッドはインスタンスがなくても呼べる
superは「親クラスのインスタンス側」を参照する概念- なので、staticの中で使うと整合性が取れずエラーになる
5.5 super を「親のインスタンスを作るもの」と勘違いする
初心者が意外と誤解しやすいのがここです。
superを使う
→ 親クラスのオブジェクトが別に生成される?
答えは NO です。
super は 別のインスタンスを作るものではなく、同じオブジェクトを親クラスとして見ている参照 です。
つまり、this と super は「別物」ではなく、
this:子クラス視点super:親クラス視点
で同じインスタンスを扱っているイメージです。
5.6 フィールドの同名は避ける(super.field が必要になる設計自体が危険)
super.field は確かに使えますが、親子で同名フィールドを持つ設計は 読みづらさとバグの温床 になりがちです。
class Parent {
int value = 100;
}
class Child extends Parent {
int value = 200; // 同名で紛らわしい
}このような場合、実務では
- フィールド名を変える
- private + getter/setter にする
- 親のフィールドをprotectedにして、子で再定義しない
などの設計のほうが安全です。
5.7 super.method() を使えば必ず親の処理が動く…とは限らない?
これは少し上級寄りですが、知っておくと混乱が減ります。
super.method()は 親クラスに定義されたそのメソッド を呼びます- ただし親メソッドの中で別のメソッドを呼んでいて、それが子でオーバーライドされている場合、結果的に子のメソッドが動くことがあります
例(理解用に簡略化):
class Parent {
void a() {
b(); // ここでb()を呼ぶ
}
void b() {
System.out.println("Parent b()");
}
}
class Child extends Parent {
@Override
void b() {
System.out.println("Child b()");
}
}このとき super.a() を呼んでも、a() の中の b() は子側に置き換わります。
public class Main {
public static void main(String[] args) {
Child c = new Child();
c.a();
}
}出力:
Child b()ポイント:
super.a()を呼んでも、内部の呼び出しは状況によって子に切り替わる- 「superで呼んだから完全に親だけ動く」とは限らない
初心者の段階では、まずは
super.method()は「親のそのメソッドを呼ぶ」
と覚えてOKですが、こういう挙動もあると知っておくと後々ラクです。
5.8 このセクションのまとめ(失敗しないためのチェックリスト)
super でつまずく原因は、ほとんどが次のどれかです。
super(...)が コンストラクタの1行目 になっていない- 親に引数なしコンストラクタがなく、
super(...)を書き忘れた this()とsuper()を両方書こうとしている- staticの中で
superを使おうとしている - 親子で同名フィールドを作って混乱している
6. まとめ(要点整理)
この記事では、Javaの super キーワードについて、初心者でも理解しやすいように 仕組み → 使い方 → 実例 → 注意点 の順に解説してきました。最後に重要ポイントを整理します。
6.1 super とは何か?
super は、親クラス(スーパークラス)を参照するためのキーワードです。
継承(extends)を使ったときに、子クラスの中から
- 親クラスのメンバー(フィールド・メソッド)
- 親クラスのコンストラクタ
を 明示的に呼び出したい場合 に使います。
6.2 super の使い方は3パターンで覚える
super の使い方は、次の3つに分類すると理解が早いです。
1) 親クラスのコンストラクタを呼ぶ
super()super(引数)
親の初期化が必ず先に行われるため、子のコンストラクタ内で親を呼び出すときに使います。
2) 親クラスのメソッドを呼ぶ
super.method()
子クラスでメソッドをオーバーライドしたときでも、親の処理を残したい(再利用したい)場合に便利です。
3) 親クラスのフィールドを参照する
super.field
親と子で同名フィールドが存在してしまったときに、親側を明示して参照できます。
6.3 this と super の違いは「どこを見ているか」
混乱しやすい this と super の違いは、次のように整理できます。
this→ 自分(子クラス側)super→ 親(親クラス側)
特にオーバーライド時は、
this.method()(またはmethod())は子の処理super.method()は親の処理
と覚えるとスムーズです。
6.4 よくあるミスは「コンストラクタ周り」が多い
super でエラーになりやすいポイントは、だいたいここに集中します。
super(...)は コンストラクタの1行目にしか書けない- 親に引数なしコンストラクタがない場合は、子で
super(引数)が必須 this()とsuper()は 同時に書けない- staticメソッド内では基本的に
superは使えない
6.5 結論:super は「親の処理を安全に再利用するための道具」
super を使いこなせるようになると、継承を使った設計で
- 共通処理を親にまとめる
- 子で拡張する
- コードの重複を減らす
といった、Javaらしい書き方ができるようになります。
まずは次の1行を確実に押さえておくと、今後の理解がかなり楽になります。
superは「親クラス版を呼ぶためのキーワード」
7. FAQ(よくある質問)
ここでは、java super を調べている人がつまずきやすい疑問を、FAQ形式でまとめます。
記事を読み終えたあとに「結局ここが不安…」となりやすい部分を、短くスッキリ解消していきます。
7.1 super はどんなときに使うべきですか?
主に次のような場面で使います。
- 親クラスのコンストラクタを明示的に呼びたい(
super()/super(引数)) - オーバーライドしたけど、親の処理も活かしたい(
super.method()) - 親と子で同名フィールドがあり、親側を参照したい(
super.field)
初心者の段階では、特に 「オーバーライド+親の処理も呼びたい」 というケースが最も理解しやすく、使いどころも多いです。
7.2 super() を書かないとどうなりますか?
親クラスに 引数なしコンストラクタが存在する場合 は、子クラスのコンストラクタ先頭に
super();が 自動で挿入される ため、基本的には問題ありません。
ただし、親クラスに 引数なしコンストラクタが存在しない場合 は、super(引数) を明示しないとコンパイルエラーになります。
7.3 super() と this() は何が違いますか?
違いは「どこを呼び出すか」です。
super()→ 親クラスのコンストラクタ を呼ぶthis()→ 同じクラス内の別コンストラクタ を呼ぶ
たとえば、コンストラクタの処理をまとめたいときは this() が便利です。
一方で、親の初期化を行いたいときは super() が必要です。
7.4 コンストラクタ内で super() と this() を両方呼べますか?
呼べません。
理由は、どちらも コンストラクタの1行目にしか書けない からです。
1行目に書けるのは
this()かsuper()のどちらか1つだけ
このルールは初心者が一番ハマりやすいので、覚えておくと安心です。
7.5 super は static メソッド内で使えますか?
基本的に使えません。
super は「親クラスのインスタンス側」を参照する仕組みですが、staticメソッドはインスタンスを作らずに呼べるため、考え方が合いません。
そのため、staticメソッド内で super を使おうとするとエラーになります。
7.6 super を使うと親クラスのインスタンスが別に生成されますか?
生成されません。
super は「親クラスのオブジェクトを新しく作る」ものではなく、同じインスタンスを親クラスとして見た参照 です。
イメージとしては、
this:子クラス視点で見るsuper:親クラス視点で見る
という「見え方の切り替え」に近いです。
7.7 super.method() と書けば必ず親の処理だけが動きますか?
super.method() で呼び出されるのは 親クラスに定義されたそのメソッド です。
ただし、親メソッドの内部で別メソッドを呼び出していて、その別メソッドが子クラスでオーバーライドされている場合、結果的に子の処理が呼ばれることがあります。
初心者の段階ではまず、
super.method()は「親のそのメソッドを呼ぶ」
と理解しておけばOKです。
7.8 super.field は積極的に使うべきですか?
多くの場合、積極的には使いません。
親と子でフィールド名が同じになっている状態は、コードが読みづらくなりやすいからです。
実務では、できるだけ 同名フィールドを作らない設計 のほうが安全です。
ただし、既存コードや外部ライブラリの都合で同名になってしまう場合に、super.field が役立ちます。
7.9 super はインターフェースでも使えますか?
基本的に super は クラス継承(extends) を前提にしたキーワードです。
ただし、Javaでは「インターフェースのデフォルトメソッド」を明示的に呼びたい場合に、少し特殊な書き方をすることがあります(例:InterfaceName.super.method())。
このあたりは中級者向けなので、まずは
- クラス継承での
super - 親クラス参照としての
super
を確実に押さえるのが優先です。
7.10 super を使いこなすコツはありますか?
最初は、次の順番で練習すると理解が早いです。
super()で親コンストラクタが先に動くことを確認するsuper.method()で親の処理を残しつつ拡張する例を書くthisとsuperの呼び分けを意識してコードを読む
特に super.method() は「継承のメリット」が直感的に分かるのでおすすめです。

