コンストラクタを定義する
インスタンス化するときに,クラス名と同じ名前のメソッドを実行していることは先に説明した.
public class Main { public static void main(String[] args) { Stack tower = new Stack(); } }
クラス名と同じメソッドを「コンストラクタ」とよぶ.コンストラクタは,クラスをインスタンス化するときに呼ばれる.クラス名と同じであり,他のメソッドとは位置づけが少し異なる.
コンストラクタは,インスタンス化するときに実行する特別なメソッドである.インスタンス化するときには,クラス名と同じ名前のコンストラクタが実行される.したがって,初期化や代入など,インスタンスを作成するときに,前処理をあらかじめ行いたいことがあるときには,コンストラクタとして定義するとよい.
もし,コンストラクタが定義されていないときには,クラス名と同じメソッド名であり,実体化する以外に実行する中身がない,空のコンストラクタが呼ばれて,インスタンス化が行われる.
例えば,これまで作成してきたStackやQueueクラスではコンストラクタが設けられていなかったが,Mainクラスなどで,インスタンス化するときに,「new」のキーワードの後でコンストラクタを実行していた.ここで呼ばれていたコンストラクタを明示的に追加すると,以下のようになる.
public class Stack { int volume; static int stackSize = 5; private int data[stackSize]; //オブジェクトを生成するだけのコンストラクタ Stack() { } //データ追加メソッド boolean push(int number) { (略) } //データ取得メソッド int pop() { (略) } //状態表示メソッド void printStack() { (略) } }
例えば,これまでは,データ領域をフィールドとして個数を固定していたが ,インスタンス化時にスタックのデータ個数を決めてインスタンス化する.これを,コンストラクタで,指定することにする.
まずは,Stackクラスにコンストラクタを定義する.これまでフィールドで指定していた,データ個数を削除し,コンストラクタで指定する.
public class Stack { int volume; private int data[]; static int stackSize = 5;
//標準サイズのためのコンストラクタ Stack() { data = new int[stackSize]; System.out.println(data.length + "個分のスタック生成"); } //データ追加メソッド boolean push(int number) { if(volume < data.length) { data[volume] = number; volume++; return true; } else { System.out.println("stack overflow"); return false; } } //データ取得メソッド int pop() { int value; if(volume > 0) { value = data[volume -1]; data[volume -1] = 0; volume--; } else { value = -1; } return value; } //状態表示メソッド void printStack() { System.out.print("|"); for(int i=0; i < data.length; i++) { System.out.print(data[i]); System.out.print("|"); } System.out.println(""); } }
public class Main { public static void main(String[] args) { Stack tower = new Stack(); tower.push(10);tower.printStack(); tower.push(20);tower.printStack(); tower.push(30);tower.printStack(); tower.push(40);tower.printStack(); tower.push(50);tower.printStack(); tower.push(60);tower.printStack(); System.out.println(tower.pop());tower.printStack(); System.out.println(tower.pop());tower.printStack(); System.out.println(tower.pop());tower.printStack(); System.out.println(tower.pop());tower.printStack(); System.out.println(tower.pop());tower.printStack(); System.out.println(tower.pop());tower.printStack(); } }
5個分のスタック生成 |10|0|0|0|0| |10|20|0|0|0| |10|20|30|0|0| |10|20|30|40|0| |10|20|30|40|50| stack overflow |10|20|30|40|50| 50 |10|20|30|40|0| 40 |10|20|30|0|0| 30 |10|20|0|0|0| 20 |10|0|0|0|0| 10 |0|0|0|0|0| -1 |0|0|0|0|0|
コンストラクタを定義して,コンストラクタを明示的に呼ぶことで,インスタンス化するときに必要とする初期化などをあらあらかじめ行ったうえで,インスタンスを扱うことができる. Javaでは,intの領域では,0に自動的に初期化されていたが,例えば,乗法的な処理をする変数であれば,データ領域をすべて1に初期化する必要があるだろう.そのように,初期値として1を代入する処理は,コンストラクタにて行うことが適切であろう.その時のコンストラクタは次のように記述できるだろう.
Stack() { data = new int[stackSize]; System.out.println(data.length + "個分のスタック生成"); for(int i=0; i < data.length;i++) { data[i] = 1; } }
このように,フィールドの初期化処理や,オブジェクトを生成するときの処理をコンストラクタにまとめることで,インスタンス化の処理を明示することができる.
演習
キュークラスのコンストラクタを明示的に定義せよ.このコンストラクタでは,フィールドで定義された,標準サイズのキューサイズのデータ領域を確保し,どれだけのサイズの配列を含むキューが生成されたか表示する.