!!! 第一章 Java プログラミングの基礎 !! 1-3. Javaプログラムの基礎 ! クラスの実際の例 それでは、先ほど作ったMassParticleクラスを例にクラス変数の宣言、初期化、代入についてみてみることにします。 ''Sample04.java'' {{pre num public class Sample04{ public static void main( String[] args){ // 変数の宣言 MassParticle p; // 質量 5 の質点オブジェクトの生成 p = new MassParticle( 5); // 初期位置を設定する p.setLocation( 10, 10); // 位置を移動させる p.translate( -5, 5); System.out.println( "mass = " + p.getMass() + ", (x,y) = (" + p.getX() + "," + p.getY() + ")"); } } }} コンパイル、実行結果は次のようになります。 {{pre C:\jprogram>javac Sample04.java C:\jprogram>java Sample04 mass = 5, (x,y) = (5.0,15.0) }} まず4行目で変数の宣言を行っています。この段階ではまだオブジェクトは生成されていません。変数の宣言方法は基本型変数と同様ですね。 7行目でオブジェクトの生成を行っています。変数pにPointクラスのオブジェクトを代入するには 変数名 = new クラス名(); としてやります。これによりPointクラスのコンストラクタ(constructor=建築者)を通じてクラスがインスタンス2化(実体化)されます。(図12) {{ref_image fig012.png}} '''図12''' クラスからオブジェクトが作られる そして代入操作によりオブジェクトへの「参照」が変数pに代入されます。変数には参照が代入されるので「参照型変数」と呼ばれます。 10、13、15行目ではMassParticleクラスのメソッドを使用しています。メソッドを使用するには、 変数名.メソッド名(); としてやります。 ところで「参照」ってなんだろうと気になってしまいますね。参照とは簡単に言えば「オブジェクトを指すもの」です。したがって変数pに入っているのはオブジェクトそのものではありません。このことをしっかり理解していないために、バグを紛れ込ませる原因になっていることがしばしば見られます。 参照を理解するためにひとつ問題を出したいと思います。Sample05.javaを見てください。このプログラムが出力する数値はいくつでしょうか? ''Sample05.java'' {{pre num import java.awt.Point; public class Sample05{ public static void main( String[] args){ // Point クラスの変数 p, q を宣言 Point p, q; // Pointクラスのオブジェクトを // (x,y) = (3,2) で作成 p = new Point( 3, 2); // q に p を代入 q = p; // q の y座標を 6 に変更 q.y = 6; double sum = p.getY() + q.getY(); System.out.println( sum); } } }} 実際に、コンパイルして実行してみましょう。実行結果は次のようになります。 {{pre C:\jprogram>javac Sample05.java C:\jprogram>java Sample05 12 }} どうですか、皆さんが予想した値と同じでしたでしょうか。多くの人は 2 + 6 = 8 と表示されると予想したのではないでしょうか。なぜ、12などという値になったのでしょう。これには参照の仕組みが深く関係しています。 分かりやすくするために図13を使いながら説明しましょう。 {{ref_image fig013.png}} '''図13''' 参照の仕組み Sample05.javaではまず6行目でPointクラスの変数 p と q が宣言されています。そして10行目でPointクラスがインスタンス化されてオブジェクトが作成されています。この状態が1. に相当します。q はまだ何も参照していません。 13行目のq = p というところで、変数pの値をqに代入しています。ここで、変数pに入っているのは先ほど作成したオブジェクトへの参照だということを思い出してください。したがって、変数qに代入されるのは位置(3,2)を表すオブジェクトそのものではなく、pが指している位置(3,2)を表すオブジェクトへの参照になります。したがってpとqは同じオブジェクトを指すことになります。これが状態 2. です。 16行目でqが指すオブジェクトのyの値を6に書き換えています。pとqは同じオブジェクトを指しているのでpの指すオブジェクトのyの値も6です。これが状態 3. です。 このとき、18行目でpの指すオブジェクトの yの値と qの指すオブジェクトの yの値を足しています。両方とも同じオブジェクトを指しているので、6 + 6 = 12 という値になります。 このように、基本型変数では値のコピーが代入されるのに対して(値渡し)、参照型変数ではオブジェクトのコピーが代入されるのではなく参照が代入されます(参照渡し)。 ところで、1. の状態で変数qにはなにが入っているのでしょう。実は何も入っていないということを表す「null」という特殊な値が入っています。nullは英語で「ない、存在しない、ゼロの」といった意味があります。参照型変数に何か格納されているかを調べるために if文を用いて {{pre if( a == null){ a = new Object(); } }} というようにして、もし空っぽならオブジェクトを作成してその参照を代入するという処理をさせることがあります。null も良く出てくるキーワードですので覚えておいて下さい。