Developer

【はじめてのJava】コンストラクタの注意点(まとめ)【クラスの継承編】
2022.02.27
Lv1

【はじめてのJava】コンストラクタの注意点(まとめ)【クラスの継承編】

はじめてのJava

このシリーズでは、初めてJavaやプログラミングを勉強する方向けに、Javaによるプログラミングの基礎を説明していきます。
目標レベルは、Javaの資格試験の一つである「Oracle Certified Java Programmer, Silver」(通称Java Silver)に合格できる程度の知識の習得です。
はじめてJavaやプログラムに触れる方にもできるだけわかりやすい解説を心がけていきます。


クラスの継承編

クラスの継承編では、Javaを扱う上で重要な「クラスの継承」について扱っていきます。

今回は今まで出てきたコンストラクタ周りのよくある注意点をまとめました。


目次


呼びなおしの注意点

コンストラクタ内で別のコンストラクタを呼びなおすことが可能です。

このとき、 コンストラクタの呼びなおしは必ず最初に行います 

OKパターンその1

class NonErrorSample{
  //コンストラクタ1
  NonErrorSample(){
    this(2); //コンストラクタ2を呼び出している★
    System.out.println(); //☆
  }
  //コンストラクタ2
  NonErrorSample(int num){
    System.out.println(num);
  }
}

OKパターンその2

class NonErrorSample extends ParentClass{
  //コンストラクタ
  NonErrorSample(){
    super(2); //親クラスのコンストラクタを呼んでいる★
    System.out.println(); //☆
  }
}

NGパターン(thisによる呼びなおしより先に処理が入りこんでいる)

class ErrorSample{
  //コンストラクタ1
  ErrorSample(){
    System.out.println(); //☆先に処理が実行されている
    this(2); //コンストラクタ2を呼び出している★
  }
  //コンストラクタ2
  ErrorSample(int num){
    System.out.println(num);
  }
}

NGパターンその2(superによる呼びなおしより先に処理が入りこんでいる)

class ErrorSample extends ParentClass{
  //コンストラクタ
  ErrorSample(){
    System.out.println(); //☆先に処理が実行されている
    super(2); //親クラスのコンストラクタを呼んでいる★
  }
}

NGパターン3(;が先に入り込んでいる)

class ErrorSample{
  //コンストラクタ
  ErrorSample(){
    ; //☆先に処理が実行されていることになる
    this(2); //コンストラクタ2を呼び出している★
  }
  //コンストラクタ2
  ErrorSample(int num){
    System.out.println(num);
  }
}

NGパターンその4(thisとsuper両方が同じコンストラクタ内に記述されている)

class ErrorSample extends ParentClass{
  //コンストラクタ
  ErrorSample(){
    super(2); //親クラスのコンストラクタを呼んでいる★
    this(2) //自分の別のコンストラクタを呼んでいる★
  }
  //コンストラクタ2
  ErrorSample(int num){
    System.out.println(num);
  }
}

継承時の注意点

クラスを継承している場合、親クラス側に引数が空のコンストラクタがないとコンパイルエラーになることがあります。

OKパターンその1(親クラス側に引数が空のコンストラクタが定義されている)

class ParentClass{
  ParentClass(){ }
}
class ChildClass extends ParentClass{ }

OKパターンその2(親クラス側にデフォルトコンストラクタが生成される)

class ParentClass{ }
class ChildClass extends ParentClass{ }

OKパターンその3(子クラス側のすべてのコンストラクタで明示的に引数付きのコンストラクタを呼んでいる)

class ParentClass{
  ParentClass(int num){ } //☆
}
class ChildClass extends ParentClass{
  ChildClass(){
    super(1); //☆を呼び出す
  }
  ChildClass(int num){
    super(num);
  }
}

NGパターン1(子クラス側で親クラスに無いコンストラクタを呼んでいる)

class ParentClass{
  ParentClass(){ } //コンストラクタはこれしかない
}
class ChildClass extends ParentClass{
  ChildClass(int num){
    super(num); //親クラスに無いコンストラクタを呼んでいる
  }
}

NGパターン2(親クラス側にないデフォルトコンストラクタを呼び出そうとしている)
※デフォルトコンストラクタは自動生成されない。

class ParentClass{
  ParentClass(int num){ } //コンストラクタはこれしかない
}
class ChildClass extends ParentClass{
  ChildClass(){
    super(); //引数が空のコンストラクタを呼び出そうとしている
  }
}

NGパターン3(こちらも親クラス側にないデフォルトコンストラクタを呼び出そうとしている)
※子クラス側にデフォルトコンストラクタが生成される。その中で親クラスのデフォルトコンストラクタを呼び出してしまうため、NGパターン2と同様エラーとなる。
※一見するとエラーに気づきにくいので注意

class ParentClass{
  ParentClass(int num){ }
}
class ChildClass extends ParentClass{ }


はじめてのJavaシリーズの目次はこちら
クラスの継承編はこちら


java 11 の練習問題一覧はこちら
はじめてのJavaシリーズの練習問題一覧はこちら