第4章 コンストラクタ
4.3 デフォルトコンストラクタとは
これまでの節でコンストラクタが、オブジェクトを生成する時に自動で必ず呼び出される機能だと学習しました。
では、必ず呼び出されるコンストラクタ機能を省略した場合に動作する、デフォルトコンストラクタの仕組みについて詳しく説明していきます。
4.3.1 デフォルトコンストラクタの仕組み
クラス内にコンストラクタ定義の記述が無い場合、オブジェクトを生成する際に以下で示すようなコンストラクタが用意され、自動的に呼び出される仕組みになっています。
コンストラクタ定義のないクラス例class Computer1 { String os; int memory; // フィールド変数の値を表示するメソッド public void show() { System.out.println("パソコンのOSは「" + os + "」です。"); System.out.println("メモリサイズは「" + memory + "MByte」です。"); } }コンストラクタ定義がないと自動で用意されるコンストラクタ
(アクセス修飾子) Computer1(){ super(); }
上記のような引数なしのコンストラクタが定義されます。アクセス修飾子はクラスのアクセス修飾子と同じになります。サンプル例だとComputer1クラスのアクセス修飾子は省略されているので、コンストラクタも省略された定義になります。処理についてですが初めて目にする「super」キーワードが記述されています。これは簡単に言うと「super();」と記述して、継承元である親クラスのコンストラクタ呼び出しを行っています。この継承の仕組みはJava基礎単元のオプションカリキュラムで改めて説明を行いますので、今は気にせずに先に進んでください。結局処理では自身の「Computer1」クラスに影響する処理は何も行っていないことになります。
このようなコンストラクタをデフォルトコンストラクタと呼びます。
Computer1 com = new Computer1();
「デフォルトコンストラクタ」の仕組みにより、本章以前でのソースコードでは「()括弧」内に引数を指定しないでオブジェクトを生成することができたのです。
ポイント
- クラス内にコンストラクタを定義しなくても、デフォルトコンストラクタが自動で用意される。但しデフォルトコンストラクタを使用するより、明示的に引数のないコンストラクタを定義することをお勧めします。
- 明示的にコンストラクタを1つでも記述(定義)した場合、デフォルトコンストラクタは作成されない。
4.3.2 デフォルトコンストラクタの注意点
クラス内に、コンストラクタを1つも定義していない場合、自動的にデフォルトコンストラクタと呼ばれる引数なしのコンストラクタが作成されます。逆に言うと1つでもコンストラクタをクラス内に定義してしまうと、引数なしのコンストラクタ(デフォルトコンストラクタ)を自動で作成しなくなるということになります。
4.2.2節のサンプル内で利用した「Computer2」クラスを例に説明を行います。
Computer2クラス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」です。"); } }
上記の「Computer2」クラスには引数ありのコンストラクタを定義しています。このようにコンストラクタが定義されていると以下のような呼び出しが行えなくなります。
オブジェクトを生成する場合は、必ずコンストラクタの引数の数とそのデータ型を一致させる必要があります。但し今回のようなケースを回避する方法がありますが、その説明は次の5章で行うことにします。
デフォルトコンストラクタが用意されるのは、クラス内にコンストラクタの定義が無い場合のみになりますので注意しておいてください。
では次の項で復習としてデフォルトコンストラクタを利用したプログラムを見てみましょう。
4.3.3 デフォルトコンストラクタを利用したプログラム
コンストラクタの定義を行っていないクラスのオブジェクト生成を行い、デフォルトコンストラクタが動作することを確認します。デフォルトコンストラクタが自動で生成される条件について学習しましょう。
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch04
③ 名前: CallDefaultConstructor
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
package jp.co.f1.basic.ch04; class Computer4 { private String os; private int memory; // コンストラクタ定義なし public void show() { System.out.println("パソコンのOSは「" + os + "」です。"); System.out.println("メモリサイズは「" + memory + "MByte」です。"); } } public class CallDefaultConstructor { public static void main(String[] args) { System.out.println("--オブジェクト生成前--"); Computer4 com = new Computer4(); System.out.println("--オブジェクト生成後--"); com.show(); } }実行結果
解説
18行目の処理でオブジェクト生成を行ったComputer4クラスにはコンストラクタ定義はありません。コンストラクタ定義を行っていないクラスはデフォルトコンストラクタが呼び出される仕組みになっています。実際デフォルトコンストラクタは何も行わないので、本当に呼び出されているのかは判断できません。しかしクラスからオブジェクトを生成する場合、必ずコンストラクタが呼び出されて動作するため、記述を省略すると何も処理を行わないデフォルトコンストラクタが追加されて動作するようになっています。
20行目でフィールド変数の値の結果を画面に出力しています。フィールド変数は規定値で初期化されています。
続いてデフォルトコンストラクタが利用できないプログラムを紹介します。
4.3.4 デフォルトコンストラクタが利用できないプログラム
クラス内にコンストラクタを定義し、デフォルトコンストラクタを呼び出そうとしたプログラムです。デフォルトコンストラクタが利用できない条件について学習しましょう。
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch04
③ 名前: NoCallDefaultConstructor
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
package jp.co.f1.basic.ch04; class Computer5 { private String os; private int memory; // コンストラクタ private Computer5(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 NoCallDefaultConstructor { public static void main(String[] args) { System.out.println("--「引数ありコンストラクタ」の実行前--"); Computer5 com = new Computer5(); System.out.println("--「引数ありコンストラクタ」の実行後--"); com.show(); } }
実行結果
引数ありのコンストラクタを定義しており、デフォルトコンストラクタが用意されない為コンパイルエラーになり実行できない。
解説
25行で引数なしでオブジェクトの生成を行っていますが、結果はコンパイルエラーになってしまいます。
Computer5 com = new Computer5();
説明するまでもないかもしれませんが、クラス内に引数ありのコンストラクタを定義しているため、デフォルトコンストラクタが自動で用意されなくなります。結果として引数なしのコンストラクタが存在していないことになり、コンパイルエラーの原因になっています。
前章までのソースコードの記述ではコンストラクタを定義していなかったので、デフォルトコンストラクタが自動で用意され引数値なしでオブジェクト生成が行えていた理由になります。