Java オブジェクト指向プログラミング最初の一歩

  正しくないプログラミング

C言語の構造体との違いを知るために、次の正しくないクラスのコードを示します。

public class Record2{//staticだけで、フィールドとメソッドを作る
	public static String sho;	// 商品コード
	public static short suu;	// 数量

	//n番目表示としてオペレータ用で画面表示する
	public static void display(int n){
		System.out.printf("%4d番目レコード:\n", n);
		System.out.printf("\t商品コード:%s\n", sho);
		System.out.printf("\t数量%d:\n", suu);	
	}
}

次に、このクラスを利用して(商品コード、数量)の2件分記憶しようとしている例を示します。
これは、正しく動作しないことを確認するプログラムです。

public class Test {

	public static void main(String[] arg) {
		Record2.sho = "A01";
		Record2.suu = 10;
		Record2.display(1);

		Record2.sho = "A03";	//"A01"が上書きされる
		Record2.suu = 5;		//10が上書きされる
		
		Record2.display(1);
		Record2.display(2);
	}
}

実行結果です。当然ですが、1件目に記憶した内容が上書きされて無くなっています。

>java Test
   1番目レコード
        商品コード:A03
        数量:5
   2番目レコード
        商品コード:A03
        数量:5

public staticが付くフィールドの sho や suu は、クラス名を付けて使えば、グローバル変数のように使えます。
よって、例えば他のクラスのメソッドで Record2.suu = 10; の ように使えるわけです。
このように、staticが付くフィールドは、クラス専用に使う変数なので、クラス変数と呼ばれます。
同様で、public staticが付くメソッドdisplayは、クラス名を付けて使えば、グローバル関数のように使えます。
よって、例えば他のクラスのメソッドで Record2.display(1); の ように使えるわけです。

  正しいプログラミング

C言語などで、関連する情報をまとめて管理する場合、構造体を使いました。
じつは、それに対応するものがクラスです。 『商品コードと数量』の構造体に対応するものを、Record2の名前のクラスで作成すると 次のようになります。 (上記に対して、staticが無くなっています。)

public class Record2{
	public String sho;	// 商品コード
	public short suu;	// 数量

	//n番目表示としてオペレータ用で画面表示する
	public void display(int n){
		System.out.printf("%4d番目レコード:\n", n);
		System.out.printf("\t商品コード:%s\n", sho);
		System.out.printf("\t数量%d:\n", suu);	
	}
}

これによって new Record2() の表記で、Record2クラスのオブジェクトが生成されます。 そのオブジェクトを、変数abに管理し、 それぞれの sho suu フィールドの 記憶域ができ、そのオブジェクトに対してdisplayメソッドの実行ができるようになります。以下に、その例を示します。

public class Test {
	public static void main(String[] arg) {
		Record2 a = new Record2();
		Record2 b = new Record2();

		a.sho = "A01";//1件目
		a.suu = 10;

		b.sho = "A03";//2件目
		b.suu = 8;

		a.display(1);//1件目表示 (オブジェクトaで、実行)
		b.display(2);//2件目表示 (オブジェクトbで、実行)
	}
}

この実行結果を以下に示します。

Z:\Java>java Test
   1番目レコード
        商品コード:A01
        数量:10
   2番目レコード
        商品コード:A03
        数量:8

Z:\Java>

  再び、正しくないプログラミング

このページ先頭で示した正しくないRecord2クラスです。

public class Record2{//staticだけで、フィールドとメソッドを作る
	public static String sho;	// 商品コード
	public static short suu;	// 数量

	//n番目表示としてオペレータ用で画面表示する
	public static void display(int n){
		System.out.printf("%4d番目レコード:\n", n);
		System.out.printf("\t商品コード:%s\n", sho);
		System.out.printf("\t数量%d:\n", suu);	
	}
}

このクラスをnew するとどうなるのでしょうか? コード例を以下に示します。

Record2 a = new Record2();
Record2 b = new Record2();
このような生成も可能ですが、Record2の各フィールドがstaticなので 実質的に各オブジェクトとして記憶可能なフィールドはありません。 ですが、次のような表現が可能です。
b.sho = "B01";
b.suu = 20;
a.display(1);
各フィールドがstaticなので、オブジェクト共通とも言える記憶(クラス変数)域更の変更です。
よってbに記憶したのに、aでも表示できていまいます。
  1番目レコード:
      商品コード:B01
      数量20:
つまり上記は、以下のようにクラスRecord2を指定した表現の次と同じなのです。
Record2.sho = "B01";
Record2.suu = 20;
Record2.display(1);
このようにstaticのフィールドやメソッドをアクセスする場合は、クラス名を指定して使った方が分かりやすい表現でしょう。
後発のプログラミング言語でC#と呼ばれるものがありますが、C#では、staticメンバを、オブジェクトの変数でアクセスできない仕様になっています。
個人的もオブジェクト変数を指定して、staticのメンバをアクセスしないようにしています。
以降において、クラスの外からstaticのメンバを指定する場合は、必ずクラス名を指定する表現で示します。