検索

キーワード


【Java】 this と super の意味や使い方、注意点をそれぞれ解説

  • 公開日:2020-09-09 14:00:23
  • 最終更新日:2021-01-25 19:36:14
【Java】 this と super の意味や使い方、注意点をそれぞれ解説

こんにちは、駆け出しプログラマーの若江です!

ここでは初学者として学習を終えた私からアウトプットの意味も込めて、

this と superについて紹介させていただきます。

できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!


関連記事リンク:継承の紹介 / コンストラクタの紹介 / メソッドの紹介 / アクセス修飾子の紹介 / フィールドの紹介 / static修飾子の紹介

this と super の使い方

Javaではプログラミングの中で「自分自身」を指す this や「親」を指す super といった単語をよく目にします。

これら this や super はクラスを特定するために使われ、

特定クラスが持つメソッドやフィールド、コンストラクタなどを呼ぶ目的で利用されます。

ここでは this や super の役割や使い方について紹介させていただきます。


this 、super の役割

this は「自分自身」、super は「親」を指します。

this、super はそれぞれが持つフィールドやメソッド、コンストラクタへアクセスするために

「自分自身」なのか「親」なのかを特定する方法として使われます。

しかしそもそもそれらを使わなくても、

クラス自身、自分が持っているフィールドやメソッドなどへのアクセスはできますし、

継承関係にある親クラスのフィールドやメソッドも子クラスでアクセスできます。

そのため this、super を使うタイミングはおおよそ決まっているとも言えます。


this と super を使うタイミング

this と super は同名のフィールドやメソッド、コンストラクタが存在する際に使います。

具体的にthis は、クラスが持つフィールド名とメソッドの引数名が同じケースでよく使われ、

super は、親と子クラスが同名のフィールドやメソッドを持っている際に区別するために、

または親コンストラクタへアクセスするケースで使われます。


またプログラマー目線では、どの(親か自分自身の)フィールドやメソッドなどへアクセスしているか、

明示的に示すことで可読性を上げることもできます。

では this、super それぞれの具体的な使い方を見ていきましょう。



this (自分自身)とは?

this は「自分自身」を指します。

クラスの様々な場所で this を使うことができるため一体誰が「自分自身」なのか混乱しますが、

this とはそのクラス自身のことを指します。


this の使い方

this はクラス自身が持つメソッドやフィールド、コンストラクタへアクセスするために使います。

メソッドやフィールド、コンストラクタでは利用方法が若干異なるため、それぞれ紹介させていただきます。


メソッドの this

自分自身のメソッドへアクセスするときは、this.メソッド名( 値 ) でアクセスできます。

メソッドを2つ持ったクラスの例として、

片方のメソッドからもう片方のメソッドへアクセスする場合のサンプルコードを見てみましょう。


◆メソッドの this の使用例

public class ThisTest {

	// 受け取った値同士を積算して返すメソッド
	public int id(int num) {
		return num * num; //「10」を渡せば「100」を返す
	}

	// 受け取った値を id メソッドで処理して、更に受け取った値を足すメソッド
	public int number(int num) {
		return this.id(num) + num; //「10」を渡せば「110」を返す
	}
}


フィールドの this

自分自身のフィールドへアクセスするときは、this.フィールド名 でアクセスできます。

フィールドの this はメソッドの引数名とフィールド名が同じ場合に使うケースが多いです。

例えばメソッドで受け取った値をそのままフィールドで保持したい場合などは、

変数名が同じであることが好ましいので、そこで this が活躍します。


◆フィールドの this の使用例

public class ThisTest {

	private int num;
	
	public int id(int num) {
		return this.num = num; // 受け取った値をフィールドへ格納
	}
}


変数名のみを記述すると、最も近い変数へアクセスをします。

上記の例で言うと num は id メソッドが持つ引数 num へアクセスします。

「return this.num = num;」の左辺のように「this.num」とすることで、

クラス自身が持つ num (フィールド)へアクセスすることができます。

代表的なものとしては「setter(セッター)」「getter(ゲッター)」でこのような記述がされます。


コンストラクタの this

自分自身のコンストラクタへアクセスする場合は、this( 引数の値 ) でアクセスできます。

コンストラクタはその性質上、コンストラクタ名とクラス名が同じため、this で呼び出しは完結します。

ただしクラスがオーバーロードしたコンストラクタを持つ事も十分予想されます。

この場合どのコンストラクタを呼び出すかは引数の型、引数の順番、引数の数で判断します。

コンストラクタの呼び出し例を見てみましょう。


◆コンストラクタの this の使用例

public class ThisTest {

	public ThisTest() {
		this("String 型のコンストラクタへアクセス");
	}

	public ThisTest(String str) {
	}
}


メソッドやフィールドは複数回でも this を使うことができますが、

コンストラクタで this を使う場合は、コンストラクタの先頭で1回だけ使うことができます。

コンストラクタで this を使う際は記述する場所と使える回数に気を付けましょう。


this が使えない場所

static の特性上、static なものから非 static なものへアクセスができないため、

自分自身を表す this を、static なものの中で使うことはできません。

 ※ static の詳しい紹介は別記事でさせていただきます。


super(親)とは?

super は継承関係と深く関わりを持っています。

継承でクラスなどが親子関係を持ったときに、子から親の機能へアクセスしたい場合に super を使います。


super の使い方

super は子クラスから親クラスのメソッドやフィールド、コンストラクタへアクセスするために使います。


メソッドの super

親クラスのメソッドは、子クラスのインスタンス生成後に super.親メソッド名( 引数の値 ) で呼ぶことができます。


◆メソッドの super 使用例

【親クラス】 メソッドを作成

public class SuperTest {

	public void parent() {
		System.out.println("親メソッド");
	}
}

【子クラス】 子メソッドから親メソッドを呼ぶ(メソッドの上下順は入れ替え可能)

public class SuperTest2 extends SuperTest {

	public void child() {
		super.parent();
		System.out.println("子メソッド");
	}
}

【インスタンスを生成するクラス】 子クラスをインスタンス化して子クラスのメソッドを使用

public class Test {
	public static void main(String[] args) {

		SuperTest2 test = new SuperTest2();
		test.child(); // 結果:「親メソッド」「子メソッド」の順に表示する
	}
}


子クラスのメソッドで「super.parent()」と「System.out.println("子メソッド")」の順を入れ替えると、

結果は「子クラス」「親クラス」の順で表示されます。(this も同様で、上下順に応じて処理されます)


フィールドの super

子クラスから親クラスのフィールドを呼ぶには、super.親フィールド名 で呼べます。


◆フィールドの super 使用例

【親クラス】 フィールドを1つ作成

public class SuperTest {

	public String str = "親フィールド";
}

【子クラス】 親フィールドを呼び出し、子フィールドを新たに作成

public class SuperTest2 extends SuperTest {

	public String str = "str =" + super.str;
	public String str2 = "str2 = 子フィールド";
}

【インスタンスを生成するクラス】 子クラスをインスタンス化して上記フィールドの値を呼び出し

public class Test {
	public static void main(String[] args) {

		SuperTest2 test = new SuperTest2();

		System.out.println(test.str); // 結果:「str = 親フィールド」を表示
		System.out.println(test.str2); // 結果:「str2 = 子フィールド」を表示
	}
}


コンストラクタの super

子クラスのコンストラクタから親クラスのコンストラクタへは、super( 引数の値 ) でアクセスできます。

基本的にはコンストラクタの this と同じルールで、子コンストラクタ内で1回のみ super を使うことができます。


◆コンストラクタの super 使用例

【親クラス】 String 型の引数を持つコンストラクタを作成

public class SuperTest {

	public SuperTest(String str) {
		System.out.println("親コンストラクタ");
	}
}

【子クラス】 子コンストラクタ内で親コンストラクタを呼び出し

public class SuperTest2 extends SuperTest {

	public SuperTest2() {
		super("");
		System.out.println("子コンストラクタ");
	}
}

【インスタンスを生成するクラス】 インスタンス生成「親コンストラクタ」「子コンストラクタ」の順に表示

public class Test {
	public static void main(String[] args) {

		SuperTest2 test = new SuperTest2();
	}
}


コンストラクタは this 同様、コンストラクタ内の最初に super を使わなくてはいけません。

super より先に何か処理を書くとエラーになります。


また子コンストラクタで super を使わなかった場合は、

暗黙的に「引数なしのコンストラクタ ( super() )」を呼びます。

【親クラス】 引数なしのコンストラクタ作成

public class SuperTest {

	public SuperTest() {
		System.out.println("親コンストラクタ");
	}
}

【子クラス】 暗黙的に「super()」を呼び出している

public class SuperTest2 extends SuperTest {

	public SuperTest2() {
	}
}

【インスタンスを生成するクラス】 子コンストラクタを呼ぶと「親コンストラクタ」を表示

public class Test {
	public static void main(String[] args) {

		SuperTest2 test = new SuperTest2();
	}
}


例とは逆に、明示的に super を使った場合は「暗黙的な引数なしのコンストラクタ呼び出し」はされません。

※コンストラクタの知識が曖昧な方はコンストラクタ紹介の記事をご一読ください。


super が使えない場所

this 同様 static なものの中から super でアクセスすることができないため注意しましょう。

また親クラスで private に指定したものも private の特性上、 super でアクセスすることはできません。



this と super の併用

先述したコンストラクタのルールでは this と super はどちらも、

「コンストラクタ内の先頭で 1回使うことができる」というものでした。

では、コンストラクタで this とsuper の両方を使いたい場合はどうなるのでしょうか?


結論として this と super を1つのコンストラクタで併用することはできません。

こういった場合は、コンストラクタ①から this でコンストラクタ②へアクセスして、

アクセス先のコンストラクタ②で super を使い親コンストラクタへアクセスします。

サンプルコードで this が使われる場所と super が使われる場所に注目してみましょう。


暗黙的な super 呼び出し

子コンストラクタで super を使わなかった場合暗黙的に super が呼ばれますが、

this を使ったコンストラクタでは 暗黙的な super の呼び出しがされません。 

下記サンプルコードでは、あえて引数なしのコンストラクタも用意しました。

this を使った際に引数なしのコンストラクタが呼ばれていないということにも注目しましょう。


◆ this と super の使用例

【親クラス】 引数なしのコンストラクタと String 型の引数を持つコンストラクタを作成

public class SuperTest {

	// 引数なしのコンストラクタ
	public SuperTest() {
		System.out.println("引数なし親コンストラクタ");
	}

	// 引数ありのコンストラクタ
	public SuperTest(String str) {
		System.out.println("引数あり親コンストラクタ");
	}
}

【子クラス】 引数なしコンストラクタで this を使用、引数ありのコンストラクタで super を使用

public class SuperTest2 extends SuperTest {

	// this を使ったコンストラクタ
	public SuperTest2() {
		this("子コンストラクタ1");
		System.out.println("子コンストラクタ2");
	}

	// super を使ったコンストラクタ
	public SuperTest2(String str) {
		super("");
		System.out.println(str);
	}
}

【インスタンス生成クラス】 「引数あり親コンストラクタ」「子コンストラクタ1」「子コンストラクタ2」の順に表示

public class Test {
	public static void main(String[] args) {

		SuperTest2 test = new SuperTest2();
	}
}


注目する点は子クラスの処理です。

子クラスのコンストラクタは以下の処理を行っています。

① public SuperTest2()」で this("子コンストラクタ1")を使い「public SuperTest2(String str)」へアクセス。

② public SuperTest2(String str)」の super("") で引数ありの親コンストラクタへアクセス。

③ 引数ありの親コンストラクタから「引数あり親コンストラクタ」を表示。

④ public SuperTest2(String str)」の次の処理 System.out.println(str) で、

  public SuperTest2()」から this("子コンストラクタ1")で受け取った「子コンストラクタ1」を表示

⑤ public SuperTest2(String str)」の処理が終わったため「public SuperTest2()へ戻り、

  this("子コンストラクタ1")の次の処理 System.out.println("子コンストラクタ2") より「子コンストラクタ2」を表示


上記のようにすれば this とsuper を併用することができます。


this.メソッドの注意点

this を使ったメソッド呼び出しは一般的ではないですが、this の挙動を知るために以下を紹介させていただきます。


メソッド①内で「this.メソッド②」を呼び出す方法を、親から継承した場合

今回「メソッドの this」で紹介させていただいた自分自身のメソッドを this で呼び出す方法を、

親クラスから引き継いで、更に子クラスで親メソッドをオーバーライドした場合、

this はどのような動きをするでしょうか?

【親クラス】 execメソッドから this を使って methodメソッドへアクセス

public class TestParent {

        public void exec() {
                this.method();
        }

        protected void method() {
                System.out.println("TestParent#method()");
        }
}

【子クラス】 親クラスを継承して、methodメソッドをオーバーライド

public class TestChild extends TestParent {

        protected void method() {
                System.out.println("TestChild#method()");
        }
}

【インスタンスを生成するクラス】 親クラスから継承した execメソッドを呼び出し

public class Test {

        public static void main(String[] args) {
                TestChild c = new TestChild();
                c.exec();
        }
}


execメソッドの this が親の method を呼ぶか、子の method を呼ぶかという問題ですが、

この場合は後者、子の method を呼ぶことになります。(  TestChild#method() を表示 )

※ execメソッドの this.method() の記述は method() でも同じ結果になります。

※この this の挙動はメソッドに限った挙動です。



まとめ

this と super はそれぞれ「自分自身」と「親」の意味を持っています。

使い方や「誰」を示しているかという点では this も super も類似する点が多いですが、

その役割は大きく異なります。

どちらもよく使われるものですので、覚えておきましょう。


関連記事リンク

継承の紹介 / コンストラクタの紹介 / メソッドの紹介 / アクセス修飾子の紹介 / フィールドの紹介 / static修飾子の紹介


【著者】

若江

30代で異業種となるIT業界へ転職した駆け出しのプログラマです。これまで主に Java や Ruby、HTML/CSS を使って学習を目的としたショップサイトや掲示板サイトの作成を行いました。プログラマとしての経験が浅いからこそ、未経験者の目線に近い形で基礎の紹介をしていきたいと思います。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様