Chapter 13

Java コンストラクタ

おでん
おでん
2021.08.14に更新

コンストラクタとは

コンストラクタは、クラス名と同じ名前で、インスタンス生成時の初期設定をするメソッドです。
つまり、インスタンス化する際に無条件で実行されるメソッドです。

コンストラクタは以下のように記述します。

アクセス修飾子 コンストラクタ名(クラス名と同一) (引数の型 引数名) {}

コンストラクタに指定できるのはアクセス修飾子(public,protected,privateなど)で、その他修飾子(static,abstract,finalなど)は指定できません。
また、コンストラクタは戻り値を持つことができません。
そのため、戻り値の型の指定がなく、return文も使用できません。

コンストラクタの呼び出し・複数宣言

また、コンストラクタを複数宣言することができます。
例えば、初期値を指定したい場合と指定したくない場合で、コンストラクタの呼び出しを変えることができます。
コンストラクタの呼び出し先の指定は、引数の型・引数の数によって行えます。
コンストラクタの呼び出しは以下の記述で行います。

new コンストラクタ名()
new コンストラクタ名(引数リスト)

見覚えのある記述です。
これは以下の記述でインスタンス化をしていました。

クラス名 変数名 = new クラス名(引数名);

実は、「=」の右辺のクラス名は、コンストラクタ名だったのです。

それでは、コンストラクタの呼び出し例です。

SetNumber.java
public class SetNumber {
  private int num1;
  private int num2;

  //int型の引数を持つコンストラクタ①
  SetNumber (int i) {
    this.num1 = 100;
    this.num2 = i;
  }
  //引数を持たないコンストラクタ②
  SetNumber () {
    this.num1 = 100;
    this.num2 = 500;
  }

  public void getNumber(){
    System.out.println(num1);
    System.out.println(num2);
  }
}
SetNumberMain.java
public class SetNumberMain {
  public static void main(String[] args) {
    //引数引き渡しているのでコンストラクタ①が呼び出される
    SetNumber numA = new SetNumber(1000);
    //引数引き渡していないのでコンストラクタ②が呼び出される
    SetNumber numB = new SetNumber();
    numA.getNumber();
    numB.getNumber();
  }
}

結果
100
1000
100
500

この場合、「SetNumber(int i)」と、「SetNumber()」という2つのコンストラクタを宣言しています。
違いは、引数があるかないかです。
呼び出しでは、「SetNumber(1000)」と、int型の引数1000と引き渡すと、コンストラクタ①が呼び出されます。
「setNumber()」と、引数引き渡さない場合は、コンストラクタ②が呼び出されます。

他のコンストラクタの呼び出し

また、コンストラクタ①と②を見ると、「this.num1 = 100;」の記述が被っています。
これは、コンストラクタを増やす度に同じ記述をする必要が出てきてしまいます。
そこで、this();によって他のコンストラクタを呼び出す方法があります。
上記の例を書き換えてみます。

SetNumber.java
public class SetNumber {
  private int num1;
  private int num2;

  //int型の引数を持つコンストラクタ①
  SetNumber (int i) {
    this.num1 = 100;
    this.num2 = i;
  }
  //引数を持たないコンストラクタ②
  SetNumber () {
    this(500);  //変更箇所
  }

  public void getNumber(){
    System.out.println(num1);
    System.out.println(num2);
  }
}

この記述でも結果は変わりません。
コンストラクタ②では、「this(500)」というint型の引数500があるので、コンストラクタ①を呼び出すことができます。
結果的に、コンストラクタ①の引数に「500」を引き渡すことができ、 「this.num1 = 100;」と「this.num2 = i;」を実行することができます。

デフォルトコンストラクタ

上記では、コンストラクタを「SetNumber」と明示的に定義していました。
しかし、これまでの解説例では特にコンストラクタを明示的に定義していませんでした。
それでも呼び出し文で「new コンストラクタ名」でインスタンス化ができていました。
これは、コンストラクタが明示的に定義されていなかった場合、自動的にコンストラクタが追加されるためです。
これをデフォルトコンストラクタと言います。
つまり、コンパイル時にクラス名から自動的にコンストラクタが呼び出し文に追加されていたのです。

スーパークラスのコンストラクタの呼び出し

クラスの継承を行う際、コンストラクタはサブクラスに継承されません。
サブクラスでスーパークラスのコンストラクタを呼び出す場合はsuperを使用します。
superはサブクラスのコンストラクタの一番初めに記述します。
以下、例です。

SuperClass.java
public class SuperClass {
  private int val;

  //コンストラクタ
  SuperClass(int a) {
      val = a;
  }
  public void getVal(){
      System.out.println(val);
  }
}
SubClass.java
public class SubClass extends SuperClass {
  //コンストラクタ
  SubClass(){
    //superでスーパークラスのコンストラクタを呼び出し
    super(10);
  }
}
SuperSubMain.java
public class SuperSubMain {
  public static void main(String[] args){
    SubClass sub = new SubClass();
    sub.getVal();
  }
}

サブクラス内で「super(10)」と記述することで、スーパークラスのコンストラクタ「SuperClass(int a)」を呼び出しています。
呼び出した「SuperClass(int a)」の引数に「10」を引き渡しています。