第4章 コンストラクタ

4.2 コンストラクタの利用方法

コンストラクタの種類には3つあることは前節で学習しました。その3種類の利用方法について説明していきます。

コンストラクタの種類

① デフォルトコンストラクタ
② 引数なしのコンストラクタ
③ 引数ありのコンストラクタ

まずはコンストラクタの基本構文を以下に示します。

書式:デフォルトコンストラクタ書式

ポイントとしてクラスブロック内に、コンストラクタを記述しないことです。コンストラクタは全てのクラスに必ず存在しなくてはなりません。そのため、コンストラクタの記述が無い場合に限り、クラスファイル生成時に、コンパイラが自動で引数なしのコンストラクタ(何も処理をしない)の記述を追加してくれます。これまでクラスを定義する際にコンストラクタを記述したことはありませんでしたが、実際にはコンパイラによって自動で生成されていたのです。なお、ソースコードに明示的にコンストラクタの記述がある場合は、このデフォルトコンストラクタの仕組みは動作しないので注意して下さい。

書式:引数なしコンストラクタ書式

ポイントとして引数なしのコンストラクタはクラスブロック内に定義します。メソッドに似た形で定義しますが、名前はクラス名と同じ、戻り値の型は記述しないことです。

凡例を見てもらうと分かるようにコンストラクタは、メソッドに非常に似ています。繰り返し説明になってしまいますが、コンストラクタの名前は必ずクラス名と同じであり、また戻り値を指定できないといった違いがあります。その他はアクセス修飾子も定義でき、引数の有無も自由に設定できる点はメソッドと同じになります。但しアクセス修飾子を「private」にしてしまうと、外部クラスから利用してオブジェクト生成ができなくなるので注意が必要です。(特殊な方法で回避方法はありますが、それは次の5章にて紹介します。)
そしてコンストラクタ内の処理は任意に記述できますが、フィールド変数の初期化を行うのが最も一般的です。

コンストラクタに戻り値の型を設定すると

コンストラクタに戻り値の型を設定してしまうと、クラス名と同じ名前を持つただのメソッドになってしまいます。初心者の頃は間違ってコンストラクタに、戻り値の型をつけてしまうこともありますので注意しましょう。

書式:引数ありコンストラクタ書式

基本的には引数なしのコンストラクタと同じですが、引数を設定するという点がポイントになります。引数設定はメソッドと同じように行えます。

引数ありのコンストラクタ設定ですが、コンストラクタ名の「()括弧」内に引数の型と引数名を設定するだけになります。今回は引数を2つ持つコンストラクタを例に挙げていますが、もちろん様々な型の組み合わせで1つでも3つ以上でも持たせることができます。
但し今回の凡例のように引数ありのコンストラクタだけ記述していると、引数なしのコンストラクタでオブジェクトの生成が行えなくなり、必ず引数ありでオブジェクトを生成しないといけなくなります。このような不便な点を回避するオーバーロードという仕組みがJavaにはあります。次の5章で学習することになりますので、今はこの言葉を覚えて次に進んで下さい。

ポイント
  • コンストラクタは引数なしや引数ありで記述することができる。記述しない場合はデフォルトコンストラクタがコンパイル時に追加される。

次にどのようにしてコンストラクタを呼び分けるのか、その記述方法について説明していきます。

書式:コンストラクタ呼び出し
この書式は引数を指定して呼び出す場合がある以外は、これまで学習してきたオブジェクト化の方法と同じです。
コンストラクタはオブジェクトを生成すると自動で動作する処理なので、処理を呼び出すために明示的な宣言は必要ありません。

  クラス名 オブジェクト変数名 = new クラス名(引数);
  

凡例:コンストラクタ呼び出し(デフォルトコンストラクタ、引数なしコンストラクタ)
本項のこれまでの凡例で紹介した「Computer1」と「Computer2」クラスを例にします。
デフォルトコンストラクタは引数なしのコンストラクタを自動で追加するので、「new Computer1()」と記述することで呼び出せます。

  Computer1 com = new Computer1( );	//デフォルトコンストラクタ呼び出し
  

この記述方法はデフォルトコンストラクタ(クラス名は異なっています)と同じになります。引数なしのため、「new Computer2()」と記述することで呼び出せます。
この呼び出し方はこれまで学習した、オブジェクトを生成する際の記述方法と同じになっています。

  Computer2 com = new Computer2( );	//引数なしのコンストラクタ呼び出し
  
ポイント
  • デフォルトコンストラクタと引数なしの呼び出し方は同じになる。違う点はコンストラクタの定義があれば引数なしコンストラクタ、定義がなければデフォルトコンストラクタが呼び出される。

凡例:コンストラクタ呼び出し(引数ありコンストラクタ)
本項のこれまでの凡例で紹介した「Computer3」クラスを例にします。

  Computer3 com = new Computer3("WindowsXP", 2048);
  

引数ありのコンストラクタを呼び出す方法は、引数なしの呼び出し方に少し追加して「()括弧」の中に値を設定すれば呼び出せます。値を設定する方法はメソッドを呼び出す方法と同じです。

ポイント
  • クラス内に引数の数および型が一致するコンストラクタが定義されていれば、そのコンストラクタが呼び出される。もしも引数の数と型が一致しない場合は、コンパイルエラーになる為間違えないように注意が必要になる。

次の項より実際のソースコードでコンストラクタが動作するサンプルを紹介していきます。

4.2.1 引数なしのコンストラクタを利用したプログラム

オブジェクトを生成すると同時にコンストラクタが動作しているのことを確認し、さらにコンストラクタを利用しフィールド変数に初期値を設定します。引数なしコンストラクタの動きや利用方法について学習しましょう。
ソースコード

① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch04
③ 名前: Constructor1
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる

  package jp.co.f1.basic.ch04;

  class Computer1 {
    private String os;
    private int memory;

    // 引数なしコンストラクタ
    public Computer1() {
      // フィールド変数に初期値を設定
      this.os = null;
      this.memory = 0;
      System.out.println("パソコンを作成しました。");
    }

    public void show() {
      System.out.println("パソコンのOSは「" + os + "」です。");
      System.out.println("メモリサイズは「" + memory + "MByte」です。");
    }
  }

  public class Constructor1 {
    public static void main(String[] args) {
      System.out.println("--「引数なしコンストラクタ」の実行前--");
      Computer1 com = new Computer1();
      System.out.println("--「引数なしコンストラクタ」の実行後--");
      com.show();
    }
  }
  
実行結果

解説
23~25行目でオブジェクトを生成したタイミングで、コンストラクタが動作することを確認しています。
実行結果のメッセージ出力タイミングを見ても分かるように、24行目でオブジェクトを生成するnew演算子の処理時にコンストラクタが動作しているのが確認できます。mainメソッド内ではコンストラクタを呼び出す処理(コンストラクタ単体では呼び出すことはできない仕様です。)は記述していないので、オブジェクトを生成すると自動でコンストラクタが動作していることも確認できます。

26行目でフィールド変数の値の結果を画面に出力しています。
実行結果から分かるようにコンストラクタで設定した値が正しく表示されています。

引数なしのコンストラクタの注意点

1)オブジェクト生成する時に、コンストラクタ定義と一致させる必要がある。

2)コンストラクタ定義と一致させない場合は、コンパイルエラーになる。
3)コンストラクタを1つも定義していない場合は、自動的にデフォルトコンストラクタが呼ばれる。

4.2.2 引数ありのコンストラクタを利用したプログラム

コンストラクタを利用しフィールド変数に任意の初期値を設定しているプログラムです。引数ありのコンストラクタを使ったフィールド変数の初期化について学習しましょう。

① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch04
③ 名前: Constructor2
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる

  package jp.co.f1.basic.ch04;

  class Computer2 {
    private String os;
    private int memory;

    // 引数ありコンストラクタ
    public Computer2(String os, int memory) {
      // フィールド変数に初期値を設定
      this.os = os;
      this.memory = memory;
      System.out.println("OS「" + os + "」メモリサイズ" + "「" + memory + "MByte」のパソコンを作成しました。");
    }

    public void show() {
      System.out.println("パソコンのOSは「" + os + "」です。");
      System.out.println("メモリサイズは「" + memory + "MByte」です。");
    }
  }

  public class Constructor2 {
    public static void main(String[] args) {
      System.out.println("--「引数ありコンストラクタ」の実行前--");
      Computer2 com = new Computer2("WindowsXP", 2048);
      System.out.println("--「引数ありコンストラクタ」の実行後--");
      com.show();
    }
  }
  
実行結果

解説

24行で引数値「WindowsXP、2048」を設定し、オブジェクトの生成を行っています。

  Computer2 com = new Computer2("WindowsXP",2048);
  

上記の処理の実行結果
OS「WindowsXP」メモリサイズ「2048MByte」のパソコンを作成しました。
26行目でフィールド変数の値の結果を画面に出力しています。
実行結果から分かるようにコンストラクタの引数で設定した値が正しく表示されています。

引数ありのコンストラクタの注意点
1)オブジェクト生成する時に、引数の数と型をコンストラクタ定義と一致させる必要がある。

2)コンストラクタ定義と一致させない場合は、コンパイルエラーになる。
3)コンストラクタを1つも定義していない場合は、自動的にデフォルトコンストラクタが呼ばれる。

コンストラクタは引数の数と型が一致するものを呼び出します。そのため、注意点については引数がある場合も、引数がない場合も全く同じになります。

4.2.3 private修飾子のコンストラクタを呼び出すプログラム

private修飾子がついたコンストラクタを持つクラスを、外部クラスから呼び出すプログラムです。アクセス修飾子によってコンストラクタのアクセス制限が行えることを確認しましょう。

① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch04
③ 名前: PrivateConstructor
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる

  package jp.co.f1.basic.ch04;

  class Computer3 {
    private String os;
    private int memory;

    // コンストラクタ
    private Computer3(String os, int memory) {
      // フィールド変数に初期値を設定
      this.os = os;
      this.memory = memory;
      System.out.println("OS「" + os + "」メモリサイズ" +
        "「" + memory + "MByte」のパソコンを作成しました。");
    }

    public void show() {
      System.out.println("パソコンのOSは「" + os + "」です。");
      System.out.println("メモリサイズは「" + memory + "MByte」です。");
    }
  }

  public class PrivateConstructor {
    public static void main(String[] args) {
      System.out.println("--newの前--");
      Computer3 com = new Computer3("WindowsXP", 2048);
      System.out.println("--newの後--");
      com.show();
    }
  }
  

実行結果
コンストラクタが外部アクセス不可能なprivateの為、コンパイルエラーになり実行できません。

Eclipse上でのソースファイル結果

解説
Computer3クラスで定義したコンストラクタのアクセス修飾子を「private」に設定しています。

25行で引数値に「WindowsXP、2048」を与えてオブジェクト生成を行っていますが、コンストラクタがのアクセス修飾子がprivateになっている為、コンパイルエラーになります。

  Computer3 com = new Computer3("WindowsXP",2048);
  


図 4.2.1:コンストラクタのアクセス制限

前章で学習したアクセス修飾子の仕組みが理解できていれば、なぜコンパイルエラーになるか直ぐに分かると思います。「Computer3」クラスが外部からアクセス可能でも、そのクラスのコンストラクタ自体がアクセス制限されてしまっているとオブジェクトの生成ができなくなってしまいます。
オブジェクト生成とコンストラクタ処理が一連の動作として組み込まれているため、今回のサンプルのようにコンストラクタに「private修飾子」が設定されていると、コンストラクタにアクセスできなくなりオブジェクト生成が不可能なケースとなってしまいます。

NEXT>> 4.3 デフォルトコンストラクタとは