はじめに
コンストラクタにおけるthisの挙動が頭の中でごっちゃになっていたので学習しました。
アウトプットを兼ねて記事投稿したいと思います。
いきなり結論
thisの役割:「自クラスの別のコンストラクタを呼び出す」
実行環境
OS:Windows10 バージョン20H2
言語:Java 8
使用ツール:Spring Tool Suite 4
1. コンストラクタのthisの使い方・動作
⑴ 使い方
自クラスの別のコンストラクタを呼び出したい場合、このように記述します。
this(引数);
もちろん引数なしでも可能です。
⑵ 動作
Public class Main {
public static void main(String[] args) {
new Test("world!!");
}
}
class Test{
public Test() {
System.out.println("Hello");
}
public Test(String val) {
this();
System.out.println(val);
}
}
上記コードではTestクラスのコンストラクタ(引数あり・引数なし)を2つ用意し、Mainクラス内でnewして引数に文字列「world!!」を記述しています。
すると、実行結果は下記の通りになります。
Hello
world!!
この場合、生成されたTestインスタンスにString型の引数があるため、引数ありのTestコンストラクタが起動します。
すると別のコンストラクタを呼び出すthisが最初に記述されているため、引数なしのコンストラクタが呼び出され、上記の実行結果が表示されます。
もちろん逆もできます。
public class Main {
public static void main(String[] args) {
new Test();
}
}
class Test{
public Test() {
this("Hello");
System.out.println("world!!");
}
public Test(String val) {
System.out.println(val);
}
}
Hello
world!!
上記コードでは、生成されたTestインスタンスに引数が無いため、引数なしのTestコンストラクタが起動します。
先程とは逆に引数ありの別のコンストラクタが呼び出され、上記の実行結果が表示されます。
2. 注意点
⑴ コンストラクタの先頭に置けない
public class Main {
public static void main(String[] args) {
new Test();
}
}
class Test{
public Test() {
System.out.println("これは");
this("エラーだ!");
}
public Test(String val) {
System.out.println(val);
}
}
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Constructor call must be the first statement in a constructor
Javaの仕様上、thisはコンストラクタ内の先頭にしか置けません。
先頭以外に記述した場合、上記の実行結果のように怒られます。
⑵ superとthisを同じコンストラクタ内で使用できない
コンストラクタにおけるsuperも、thisと同様にコンストラクタ内の先頭にしか置けません。
そのため、superとthisを1つのコンストラクタ内で併用することは不可能です。
3. でもthisとsuperの2つを使いたいときあるじゃん!
仰る通りです。
1つのクラス内であれば可能です。
public class Main {
public static void main(String[] args) {
new Test();
}
}
class SuperTest{
public SuperTest() {
System.out.println("親!");
}
}
class Test extends SuperTest{
public Test() {
this("Hello!!");
System.out.println("world!!");
}
public Test(String val) {
super();
System.out.println(val);
}
}
親!
Hello!!
world!!
チョット複雑ですが、以下のような処理が行われています。
⓵ 引数なしのTestインスタンスが生成されて、引数なしのコンストラクタ、public Test()
を呼び出す。
⓶ 他のコンストラクタを呼び出すthis("Hello!!")
が起動し、引数ありのコンストラクタ、public Test(String val)
が呼び出される。
⓷ 親クラスのコンストラクタを呼び出すsuper()
によって親クラスの引数なしコンストラクタ、SuperTest()
にアクセスし、「親!」を表示する。
⓸ super()
の処理が終わったため、今度は引数ありのコンストラクタ、Test(String val)
がTest()
内のthis("Hello!!")
で受け取った文字列「Hello!!」を表示する。
⓹ this("Hello!!")
の処理が終わったため、Test()
にて文字列「world!!」を表示する。
上記のような動作が行われるため、別々のコンストラクタであれば、superとthisを1つのクラス内で使用することが可能です。
参考資料
【参考記事】