Java入門 第7回 修飾子と可視性・変数の種類

■修飾子とアクセス制御
main()はJavaが実行されると最初に呼び出される特別なメソッドであることは前回簡単に説明しました。
改めてmain()を眺めてみましょう。

public static void main(String args[])

staticがつくとそのメソッドや変数はインスタンスしないで利用することができます。main()は最初に実行されるメソッドなので必ずstatic がつきます。
void は戻り値を持たないメソッドであること、括弧の中は引数ですからString型の配列変数args[]を引数に持つことが分かります。
この引数はいつどのように渡すのでしょうか。
実はStirng args[]はコマンドライン引数といってJavaを実行するとき次のように指定します。

C:\kikuchi\JavaRensyu>java Sample07 2006 09
受け取る側は配列args[]を指定します。
String year;
String month; year = args[0]; month = args[1];
コマンドライン引数を使えばプログラムに簡単に値を渡すことができます。
(ただしString型ですので計算に利用したい場合は他の型に変換する必要があります。)

・アクセスレベルと可視性
public はアクセス制限に関する修飾子で、そのメソッドがどのくらいのアクセス制限をしているかを示します。
publicがついたメソッドはどこからでも自由に利用することができます。
名称 アクセスレベル
public 特にアクセスを制限しない
protected 同じパッケージ内から呼び出すことができる 自クラスを継承したサブクラスから呼び出すことができる
指定なし 同じパッケージ内から呼び出すことができる
private 自クラスからのみ呼び出すことができる
クラスの継承については次回説明します。
補足しますと、パッケージとは同一ディレクトリ内とほぼ同じ意味です。これまで見てきたサンプルソースは特にアクセス制限を付けていませんから同じディレクトリにあるクラスは互いに呼び出すことができます。
例を見てみましょう。
class Kaiin{
	String name;
	String address;
	void Disp(){
		System.out.println("名前:"+ name);
		System.out.println("住所:" + address);
	}
}			
class Sample06{
        public static void main(String args[]){
	        Kaiin kihon;
	        kihon = new Kaiin();
	        kihon.name ="Java 花子";
	        kihon.address="千代田区神田佐久間町";
	        kihon.Disp();
	        Regist info = new Regist();//Sample07.javaで作成したクラスです

	}
}
			
・実行結果
C:\kikuchi\JavaRensyu>java Sample06
名前:Java 花子
住所:千代田区神田佐久間町
会員情報を登録してください

C:\kikuchi\JavaRensyu>
			
特にアクセス制限をかけずどこからでも自由に利用できるというと便利そうですが、実はプログラミング的には好ましくありません。

▲ページの先頭へ戻る

不正な値を入力さてもチェックできませんし、クラスは作った人だけが利用するものではないからです。
クラスは内部の処理が分からなくても、機能を知っていれば利用できるというのが理想的な形です。
例えばMath.random()というメソッドが内部でどんな処理をしているのか知らなくても、0.1から1.0までの乱数を返すという機能を知っていれば利用することができます。
これをJavaに詳しい人が勝手に書き換えたらとても困りますよね。
このようなことを回避するためにprivateを付けます。
前回のサンプルソースを改良してみましょう。
class Kaiin{
	//フィールドはprivateにしました
	private String name;
	private String address;
	}
	//メソッドはpublicにしました
	public void Disp(){
		System.out.println("名前:"+ name);
		System.out.println("住所:" + address);
	}	
}			
public class Sample08{
public static void main(String args[]){
	Kaiin kihon;
	kihon = new Kaiin();
	kihon.name ="Java 花子";
	kihon.address="千代田区神田佐久間町";
	kihon.Disp();
	}
}
			
このままだとコンパイルエラーが出ます。privateにしたフィールドには直接値を代入できないからです。
値を設定するにはセッター(setter)と呼ばれるメソッドを用意します。
セッターは普通setXxxxxという形式の名前を付けます。
class Kaiin{
	//フィールドはprivateにしました
	private String name;
	private String address;
	//セッター
	public void setName(String name){
		this.name = name;
	}
	public void setAddress(String address){
		this.address = address;
	}
	public void Disp(){//メソッドはpublicにしました
		System.out.println("名前:"+ name);
		System.out.println("住所:" + address);
	}
	
}			
public class Sample08{
public static void main(String args[]){
	Kaiin kihon;
	kihon = new Kaiin();
	kihon.setName("Java 花子");
	kihon.setAddress("千代田区神田佐久間町");
	kihon.Disp();
	
	}
}			
			
今度はちゃんとコンパイル・実行できましたね。
自クラスであることを明示的に表すときthis を付けます。
逆に値を得る場合にはゲッター(getter)と呼ばれるメソッドを用意します。
class Kaiin{
	//フィールドはprivateにしました
	private String name;
	private String address;
	//セッター	
	public void setName(String name){
		this.name = name;
	}
	public void setAddress(String address){
		this.address = address;
	}
	//ゲッター
	public String getName(){
		return name;
	}
	public String getAddress(){
		return address;
	}
	public void Disp(){//メソッドはpublicにしました
		System.out.println("名前:"+ name);
		System.out.println("住所:" + address);
	}
	
}			
public class Sample08{
public static void main(String args[]){
	Kaiin kihon;
	kihon = new Kaiin();
	kihon.setName("Java 花子");
	kihon.setAddress("千代田区神田佐久間町");
	//kihon.Disp();
	
	System.out.println("名前:" + kihon.getName());
	System.out.println("住所:" + kihon.getAddress());
	}
}
			
・実行結果
C:\kikuchi\JavaRensyu>java Sample08
名前:Java 花子
住所:千代田区神田佐久間町

C:\kikuchi\JavaRensyu>
			
ゲッターを使うとprivateな値を他のクラスから得られることが理解できたでしょうか。

・staticとクラス変数
最後にstaticについて簡単に説明します。
staticを付けたメソッドや変数はインスタンスしないで使えると説明しましたが、だからといって何でもstaticで宣言していいわけではありません。
staticな変数やメソッドはクラス全体に関連付けられているからです。 もう少し分かりやすくいうと、staticで変数を宣言した場合、その変数はひとつしか生成されないのでクラス全体でひとつの変数を使うことになります。
static のついた変数をクラス変数、メソッドをクラスメソッドと言うのに対し、今までのサンプルソースのように宣言しインスタンス化して使うものをインスタンス変数、インスタンスメソッドと呼びます。
インスタンス変数・メソッドは各オブジェクトに関連付けられています。
また、各メソッド内で定義された変数はローカル変数と呼びます。
簡単な例を挙げますのでそれぞれ値がいくつになるか考えてみてください。
class Hensu{
	static int a=0;	//クラス変数です
	int b=0;		//インスタンス変数です

	void test(){	//インスタンスメソッドです
		int c;		//ローカル変数です
		for(c=0;c<100;c++){
			a = ++a;
			b = ++b;
		}
	System.out.println("a=" + a);
	System.out.println("b=" + b);
	System.out.println("c=" + c);
	}
}
class Sample09{
public static void main(String args[]){
	Hensu inst1;
	inst1 = new Hensu();
	Hensu inst2;
	inst2 = new Hensu();
	inst1.test();
	inst2.test();

	}
}
結果はこのようになります。
C:\kikuchi\JavaRensyu>java Sample09
a=100
b=100
c=100
a=200
b=100
c=100

C:\kikuchi\JavaRensyu>
予想と合っていましたか?
次回はクラスの継承について解説します。