Part4では,インスタンスを生成しなくても使うことができるJavaのクラス変数,クラスメソッド,そしてコンストラクタの使い方について学びます。

 最初に,オブジェクト指向の基本をおさらいしながら,Javaがクラス変数とクラス・メソッドを採り入れた理由を説明していきます。これまで説明してきた範囲では,クラスが備える変数やメソッドは,クラスからインスタンスを生成すると初めて使えるようになりますね。これは,「クラスからオブジェクトを生成し,そのオブジェクトが連携して処理する」というオブジェクト指向の考え方に,よくあてはまります。こうした変数とメソッドをそれぞれ,インスタンス変数,インスタンス・メソッドと呼びます。

 ところが,この考え方を処理系としてそのまま実装すると無駄が発生することがあるのです。例えばオブジェクトが一つしか必要ない場合を想像してください。その場合,いちいちクラスからインスタンスを生成して,変数やメソッドを使うのはあまり効率が良いとは言えません。クラスからインスタンスを生成する際には,メモリー上のクラスをひな型にして,インスタンス用のメモリー領域を別に確保するため,そのぶんの時間やメモリー領域が必要になるからです。クラス内の変数やメソッドを直接利用できるようにしたら,インスタンスを生成しないぶんだけ処理スピードが上がり,メモリーを消費することもなくなります。そこでJavaでは,こうしたことができる仕組みを提供しているのです。インスタンスを生成せずに直接利用できるクラス内の変数とメソッドをそれぞれ,クラス変数,クラス・メソッドと呼びます。

 例えば,Java言語にはMathというクラスがあります。円周率などを変数(フィールド)として持ち,メソッドとして平方根などの数式を演算する機能を持つクラスです。このクラスのフィールドとメソッドは,すべてクラス変数とクラス・メソッドです。円周率などフィールドとして持っている値は変わることがありません。数式の演算は引数を渡して結果を得るだけです。このため,インスタンスを複数用意する必要がないのです。もちろん,インスタンスが複数あっても困らないのですが,常に同じ値と同じ結果を返す関数が複数あって無駄なだけです。プログラム全体で一つだけあれば十分なものは,クラス変数やクラス・メソッドにする。こうすると効率よくプログラムを作れるのです。

 クラス変数とクラス・メソッドを定義するには,宣言時にpublicやprivate修飾子の後ろにstaticと追加します。もともと修飾子がない場合は先頭に付けます。

 次に,クラス変数とクラス・メソッドを使ったサンプル・プログラムを紹介しましょう。リスト1は肥満度を表す指標ボディ・マス・インデックス(BMI)を計算する機能を持つBmi1クラスです。

リスト1●BMIを計算するクラス(Bmi1クラス)。2~3行目がクラス変数(定数)。4~6行目がクラス・メソッド
リスト1●BMIを計算するクラス(Bmi1クラス)。2~3行目がクラス変数(定数)。4~6行目がクラス・メソッド
[画像のクリックで拡大表示]

 このクラスは,BMIの計算で利用する数値をクラス変数で宣言しています。またこの値は変更できないようにfinal修飾子を付けて定数にし,宣言と同時に初期化しています。Bmi1クラスには,体重と身長からBMIを計算するgetBmiメソッドがあります。このメソッドもstatic修飾子が付いているのでクラス・メソッドになります。

 Bmi1クラスのクラス変数,クラス・メソッドを利用するTest1クラスを作ってみましょう(リスト2)。

リスト2●Bmi1クラスを使ってBMI値を計算するクラス(Test1クラス)
リスト2●Bmi1クラスを使ってBMI値を計算するクラス(Test1クラス)
[画像のクリックで拡大表示]

 クラス変数やクラス・メソッドは,クラス・ファイルをメモリーに読み込んだ時点で使用可能になります。インスタンス変数やインスタンス・メソッドのように,new演算子を使っていちいちインスタンスを生成する必要がありません。アクセスするには「クラス名.クラス変数名」あるいは「クラス名.クラス・メソッド名( )」のように記述します。

 Test1クラスのmainメソッドでBmi1クラスのクラス・メソッドとクラス変数を呼び出しているところを見てください(Test1クラスのmainメソッドは,static修飾子が付いていますからクラス・メソッドです。mainメソッドは,インスタンスを生成しなくてもJava仮想マシンが呼び出せるように,クラス・メソッドになっているのです)。

 インスタンスを生成せずに,「Bmi1.getBmi(myWeight, myHeight)」「Bmi1.MIN」のようにクラス名につなげてメソッドや変数を指定していますね。実際にコンパイル・実行するときは,体重と身長をあなた自身の値に置き換えてみてください。実行すると,あなたのBMIを計算して,判定結果を表示します(図1)。

図1●Test1クラスの実行結果
図1●Test1クラスの実行結果

 同じクラス内でクラス変数やクラス・メソッドを使う場合は,クラス名を省略できます(リスト3)。これは同じインスタンス内でインスタンス変数/メソッドにアクセスする際にインスタンス名を省略できるのと同じです。

リスト3●リスト1とリスト2をまとめて一つのクラスに記述した例(Bmi2クラス)。クラス名を付けずに,getBmiメソッドなどを呼び出せる
リスト3●リスト1とリスト2をまとめて一つのクラスに記述した例(Bmi2クラス)。クラス名を付けずに,getBmiメソッドなどを呼び出せる
[画像のクリックで拡大表示]