Javaは小さな部品単位でプログラムを作成して、部品を組み合わせることで大きなシステムを構築します。
しかしクラスを部品として再利用するには、それぞれのクラスが安定して動かなければなりません。クラスのフィールドに不正な値が設定されたりするとまずいわけです。
例えば以下のようにフィールドを他のクラスから簡単に変更できると、本来ありえない値も設定できてしまいます。
people[0].age = -15;
people[1].age = -25;
プログラムの実行結果を見ると、年齢がマイナスになっています。

age はint(整数)で宣言しているので、データ型としてはマイナスが入ってもエラーにはなりませんが、年齢という意味を考えるとマイナスはおかしいですよね。
このような値が後に不具合の原因になります。これではクラスが安定して動作しているとはいえません。
そこでクラスの外部からはフィールドを直接操作できないようにして、必ずメソッドを経由してフィールドを間接的に操作するようにします。これをカプセル化といいます。メソッドを経由することで、データをチェックしてからフィールドに設定できます。
カプセル化はクラス、フィールド、メソッドに適切な「修飾子」を付けることで簡単にできます。アクセス修飾子には、public、protected、指定なし、private などがあり、クラス、フィールド、メソッドで使える修飾子が異なります。
【1】sample06 フォルダをフォルダごとコピーして、sample07 フォルダを作ります。

【2】sample07 の PersonTest.java を以下のように変更します。変更のポイントはアクセス修飾子の private を付けたことです。このプログラムをコンパイルするとエラーになりますがわざとです。
保存先 C:\java\sample07
ファイル名 PersonTest.java
public class Person {
private String name;
private int age;
private String address;
public Person(String _name, int _age, String _address) {
name = _name;
age = _age;
address = _address;
}
public void say(){
System.out.println("私の名前は" + name + "です。年齢は"
+ age + "才で、住所は" + address + "です。");
}
}
public class PersonTest {
public static void main(String[] args) {
Person[] people = new Person[2];
people[0] = new Person("太郎", 21, "東京都港区");
people[1] = new Person("花子", 18, "北海道札幌市");
for(int i = 0; i < people.length; i++){
people[i].say();
}
System.out.println("データを変更。");
people[0].name = "次郎";
people[0].age = 15;
people[0].address = "福岡県福岡市";
people[1].name = "桃子";
people[1].age = 25;
people[1].address = "宮城県仙台市";
for(int i = 0; i < people.length; i++){
people[i].say();
}
}
}
【3】以下の図を参考に、カレントディレクトリの切り替え、コンパイルを行います。このプログラムをコンパイルするとエラーになりますが、エラーメッセージからどのような問題点があるのか考えてみます。

エラーメッセージが少しわかりにくいので、補足して説明します。
(1)クラス Person は public クラスなので、ファイル名は Person.java にしなければなりません。public クラスは1つのファイルに1つしか書けないからです。
(2)フィールドにアクセス修飾子の private を付けたことで、他のクラスからは直接アクセスできないというエラーです。
(3)エラーが7個あることを表しています。
つまりソースファイルをクラスごとに分けて、Personクラス側にフィールドを間接的に操作するためのメソッドを用意して、PersonTest側からはこのメソッドを呼び出すようにすれば、エラーは解決します。次回に修正してみましょう。
【解説】
実はこれまでクラス、フィールド、メソッドは簡略形で書いていました。[]カッコは省略できることを表しています。
(1)クラスの書式
・正式形
[修飾子] class クラス名[extends節][implements節] {
内容
}
・簡略形
class クラス名 {
内容
}
(2)フィールドの書式
・正式形
[修飾子] 変数の型 フィールド名;
・簡略形
変数の型 フィールド名;
(3)メソッドの書式
・正式形
[修飾子] 戻り値の型 メソッド名(仮引数のリスト){
内容
return 戻り値;
}
・簡略形
戻り値の型 メソッド名(仮引数のリスト){
内容
return 戻り値;
}
(4)主な修飾子
・public :すべてのクラスからアクセス可能。
・protected :同一クラス内、同一パッケージ、サブクラスからアクセス可能。
・指定なし :同一クラス内、同一パッケージからアクセス可能。
・private :同一クラス内のみアクセス可能。
*パッケージについては別の機会に説明します。今の段階では同じフォルダ内と考えてください。
これまで書いていたプログラムは「指定なし」の設定になっていました。修飾子をつけなくても同じフォルダ内のクラスだったので、PersonTestクラスからPersonクラスを利用できたのです。