第8章の Employee クラスは、e1.age = 27; のように、フィールドをどこからでも直接書き換えられました。この章では、フィールドを外から隠し、メソッドを通して読み書きする カプセル化 の書き方を学びます。Spring入門の Entity と Form は、すべてこの形で書きます。あわせて、クラスを整理する パッケージ と import、クラスに1つだけ持つ static なフィールドも学びます。
この章で学ぶこと
- アクセス修飾子(
public・private・修飾子なし) - getter と setter、Eclipse による自動生成
- カプセル化の考え方
- パッケージと
import、補完によるimportの自動追加 -
staticなフィールドと定数(static final)
9.1 この章で作るもの
この章では、社員のクラス Employee を ch09.entity パッケージに、それを使う Main を ch09 パッケージに作ります。パッケージを分けるのは、import を学ぶためです。章の最後には、Main を実行するとコンソールに次のように表示されるようになります。
雷禅 海皇(26歳)
雷禅 海皇(27歳)
年齢の上限:99
| ファイル | 作業 | 内容 |
|---|---|---|
ch09/entity/Employee.java |
新規 | 社員を表すクラス。フィールドを private にし、getter と setter を付ける |
ch09/Main.java |
新規 |
Employee を使うクラス(main あり) |
9.2 フィールドを private にする
-
srcを右クリックし、新規 → パッケージ で、名前にch09.entityと入力して作ります。名前の.で区切ると、ch09の中のentityという2段のパッケージになります。パッケージ・エクスプローラーにはch09.entityと1行で表示されます。 -
ch09.entityパッケージを右クリックし、新規 → クラス で、名前Employee、mainの チェックを入れずに クラスを作ります。 -
緑の行を入力します。フィールドの先頭に
privateを付けます。ch09/entity/Employee.javapackage ch09.entity; /** 社員を表す */ public class Employee { private String name; private int age; } -
getter と setter を、Eclipse に作ってもらいます。フィールドの下の行(最後の
}の行)をクリックしてから、メニューの ソース → getter および setter の生成 を選びます。「すべて選択」をクリックして
nameとageの両方にチェックを入れ、「生成」をクリックします。次のメソッドが書き足されます。ch09/entity/Employee.javapackage ch09.entity; /** 社員を表す */ public class Employee { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }自動生成されたメソッドは、自分で入力してもかまいません。Spring入門では、この形のメソッドを何十個も書くので、Eclipse の生成に慣れておくと楽です。
-
保存します。
private を付けたフィールドは、そのクラスの中からしか使えません。別のクラスから e1.name と書くとエラーになります。代わりに、public のメソッド getName()・setName(…) を通して読み書きします。
9.3 アクセス修飾子
public や private のように、「どこから使えるか」を決める言葉を アクセス修飾子 といいます。フィールド・メソッド・コンストラクタ・クラスに付けられます。
| 修飾子 | 使える範囲 | この教材での使い方 |
|---|---|---|
public |
どこからでも | クラス、メソッド、定数 |
private |
同じクラスの中だけ | フィールド |
| (書かない) | 同じパッケージの中だけ |
第8章までの練習で使った。これからは、フィールドは private、メソッドは public と書く |
ほかに protected という修飾子もありますが、この教材と Spring入門では使いません。
【知識メモ】public なクラスとファイル名
クラスに public を付けると、どのパッケージからでも使えるクラスになります。public なクラスは、1つのファイルに1つだけ 書け、クラス名とファイル名を同じにする決まりです。Eclipse でクラスを作ると、最初から public class になっています。
9.4 getter と setter
フィールドの値を返すメソッドを getter(ゲッター)、値を入れるメソッドを setter(セッター)といいます。名前の付け方が決まっています。
| 種類 | 名前 | 形 | 例(フィールド age) |
|---|---|---|---|
| getter |
get + フィールド名の先頭を大文字に |
引数なし。フィールドの型を返す | public int getAge() { return age; } |
| setter |
set + フィールド名の先頭を大文字に |
フィールドの型の引数を1つ受け取る。void
|
public void setAge(int age) { this.age = age; } |
setter の this.age = age; は、第8章のコンストラクタと同じで、「このオブジェクトのフィールド age に、引数の age を入れる」という意味です。
カプセル化
フィールドを private にして、getter と setter を通してだけ読み書きできるようにすることを カプセル化 といいます。手間が増えるように見えますが、次の利点があります。
- 値を読む場所と書く場所が、
getAge()・setAge(…)の呼び出しに限られるので、どこで値が変わったのかを追いやすい - 後から「年齢は 15 以上 99 以下だけ受け付ける」のような確認を setter に足しても、使う側のコードを変えなくてよい
- フィールドの名前や型を変えることになっても、getter と setter の中だけ直せばよい
【知識メモ】Spring入門での getter と setter
Spring入門の Entity と Form は、すべて「private のフィールド + public の getter と setter」の形です。Spring や画面のテンプレートは、employee.name と書かれていたら getName() を呼び、画面から入力された値は setName(…) で入れる、という決まりで動きます。名前の付け方を守ることが、Spring を使うときの前提になります。
9.5 パッケージと import
Employee を使う Main クラスを、別のパッケージ ch09 に作ります。別のパッケージのクラスを使うには、import が必要です。
-
srcを右クリックし、新規 → パッケージ でch09パッケージを作ります。すでにch09.entityがありますが、ch09自体は別のパッケージとして作ります。 -
ch09パッケージを右クリックし、新規 → クラス で、名前Main、mainに チェックを入れて クラスを作ります。 -
// TODOの行を消し、mainメソッドの中にEmpと入力して Ctrl + Space を押します。候補に「Employee - ch09.entity」が出るので、↑ ↓ キーで選んで Enter キーを押します。第8章で作った「Employee - ch08」も並ぶので、必ずch09.entityのほうを選びます。
図9-2 候補から Employee - ch09.entity を選ぶ(赤枠)Employeeと入力されると同時に、ファイルの上のほうにimport ch09.entity.Employee;の行が自動で書き足されます。 -
続けて、緑の行を入力します(
importの行は、補完で入っているはずです)。ch09/Main.javapackage ch09; import ch09.entity.Employee; public class Main { public static void main(String[] args) { Employee e1 = new Employee(); e1.setName("雷禅 海皇"); e1.setAge(26); System.out.println(e1.getName() + "(" + e1.getAge() + "歳)"); e1.setAge(e1.getAge() + 1); System.out.println(e1.getName() + "(" + e1.getAge() + "歳)"); } } -
保存して実行します。
コンソール雷禅 海皇(26歳) 雷禅 海皇(27歳) -
試しに、
e1.setAge(26);の次の行にe1.age = 26;と書いてみてください。「フィールド Employee.age は不可視です」というエラーになります。privateのフィールドは、別のクラスから使えません。確かめたら、その行は消します。
パッケージ
パッケージ は、クラスを分類して入れておくフォルダーです。パッケージ名は、フォルダーの階層を . でつないだもので、ch09.entity は ch09 フォルダーの中の entity フォルダーです。クラスの正式な名前は、パッケージ名を付けた ch09.entity.Employee になります。パッケージが違えば、同じ Employee という名前のクラスを別々に作れます(第8章の ch08.Employee と、この章の ch09.entity.Employee は別のクラスです)。
【知識メモ】現場でのパッケージ名
現場では、com.example.employeeapp.entity のように、会社のドメイン名を逆にしたものから始める名前を付けます。世界中のどのクラスとも名前が重ならないようにするためです。Spring入門でもこの形を使います。この教材では、短くするために章の名前にしています。
import
別のパッケージのクラスを使うときは、ファイルの先頭(package の行の後)に import パッケージ名.クラス名; と書きます。これを書いておくと、本文では Employee と短い名前で書けます。
| 使うクラス | import |
|---|---|
| 同じパッケージのクラス | 不要(第8章の Main から Employee を使えたのはこのため) |
java.lang パッケージのクラス(String・System・Integer など) |
不要(Java の基本のクラスなので、最初から使える) |
それ以外のクラス(別のパッケージの自作クラス、java.util.List、java.util.Date など) |
必要 |
【便利な使い方】import は補完で入れる
import の行は、手で書かずに、クラス名を補完(名前の一部を入力して Ctrl + Space)で入力すると自動で書き足されます。クラス名を全部手で打ってしまったときは、その名前の末尾にカーソルを置いて Ctrl + Space を押すと、同じように import が入ります。ファイル全体の import をまとめて整えたいときは、Ctrl + Shift + O キー(インポートの編成)も使えます。
9.6 static なフィールドと定数
フィールドはオブジェクトごとに持ちますが、「年齢の上限は 99」のように、クラスに1つだけあればよい値 もあります。そのような値には static を付けます。値を変えない定数なら、第4章で学んだ final も付けます。
-
Employee.javaに、緑の行を書き足します。ch09/entity/Employee.java(前半)package ch09.entity; /** 社員を表す */ public class Employee { /** 年齢の上限 */ public static final int MAX_AGE = 99; private String name; private int age; -
Main.javaのmainメソッドの最後に、緑の行を書き足します。ch09/Main.java(main メソッドの最後)System.out.println(e1.getName() + "(" + e1.getAge() + "歳)"); System.out.println("年齢の上限:" + Employee.MAX_AGE); } -
保存して実行します。最後に、次のように表示されます。
コンソール(最後の行)年齢の上限:99
static なフィールドは、オブジェクトを作らなくても クラス名.フィールド名 で使えます。e1.MAX_AGE とは書かず、Employee.MAX_AGE と書きます。
static の意味
第7章では、main から呼ぶメソッドに static を付けると説明しました。static の意味は、フィールドでもメソッドでも同じで、「オブジェクトではなく、クラスに属する」です。
static あり |
static なし |
|
|---|---|---|
| フィールド | クラスに1つ。Employee.MAX_AGE
|
オブジェクトごとに1つ。e1.getAge() で読む age
|
| メソッド | オブジェクトを作らずに呼べる。AgeChecker.isValid(27)、Integer.parseInt("26")(第11章) |
オブジェクトに対して呼ぶ。e1.getName()
|
main メソッドに static が付いているのは、プログラムを開始した時点ではまだオブジェクトが1つも無いので、オブジェクト無しで呼べる必要があるからです。
【知識メモ】Spring入門の serialVersionUID
Spring入門の Form クラスには private static final long serialVersionUID = 1L; という行があります。「クラスに1つ(static)の、値を変えない(final)、long 型の定数で、値は 1L」と読めます。この定数が何のためにあるかは、第10章の Serializable で説明します。
9.7 うまくいかないときは
| 症状 | 考えられる原因と対処 |
|---|---|
| 「フィールド Employee.age は不可視です」 |
private のフィールドを別のクラスから直接使っています。getAge()・setAge(…) を使ってください。 |
| 「Employee を型に解決できません」 |
import ch09.entity.Employee; が無いか、打ち間違っています。Employee の末尾にカーソルを置いて Ctrl + Space を押し、import を入れてください。 |
| 「インポートされた ch09.entity.Employee は見つかりません」 |
Employee クラスが ch09.entity パッケージにありません。パッケージ名の打ち間違い(entitiy など)を確かめてください。 |
| 「宣言されたパッケージ "ch09" が、予想されているパッケージ "ch09.entity" に一致しません」 | クラスのある場所と package の行が合っていません。クラスを作ったパッケージに合わせて package の行を直してください。 |
| 「メソッド setName(String) は型 Employee で未定義です」 | setter の名前が違います。set + フィールド名の先頭を大文字(setName)にします。「getter および setter の生成」を使うと間違えません。 |
ほかのコンパイルエラーは、付録A「よくあるコンパイルエラー」 も参考にしてください。
9.8 まとめと確認問題
まとめ
-
アクセス修飾子:
publicはどこからでも、privateは同じクラスの中だけ、書かなければ同じパッケージの中だけ - フィールドは
privateにして、publicの getter(getXxx())と setter(setXxx(値))で読み書きする(カプセル化)。Eclipse の「ソース → getter および setter の生成」で作れる -
パッケージ はクラスを入れるフォルダー。別のパッケージのクラスを使うには
import パッケージ名.クラス名;を書く。同じパッケージとjava.langのクラスには不要。importは補完で自動で入る -
staticは「クラスに属する」。staticなフィールドやメソッドはクラス名.名前で使う。定数はpublic static final 型 名前 = 値;
この章で使った書き方は、付録B「文法早見表」の「メソッドとクラス」 にまとめています。
確認問題
問1 フィールド private String address; の getter と setter を書いてください。
解答を見る
public String getAddress() { return address; } と public void setAddress(String address) { this.address = address; } です。
問2 フィールドを private にする利点を1つ答えてください。
解答を見る
値を読み書きする場所が getter と setter に限られるので、どこで値が変わったのかを追いやすくなります。後から setter に確認の処理を足しても、使う側のコードを変えなくて済むことも利点です。
問3 ch09.entity パッケージの Employee クラスを、ch09 パッケージのクラスから使うために書く import の行を答えてください。
解答を見る
import ch09.entity.Employee;
問4 String や System を使うときに import が不要なのはなぜですか。
解答を見る
java.lang パッケージのクラスは、Java の基本のクラスとして最初から使えるようになっているためです。
問5 public static final int MAX_AGE = 99; の static と final は、それぞれ何を表していますか。
解答を見る
static は「オブジェクトごとではなく、クラスに1つだけ持つ」こと、final は「値を後から変えられない」ことを表します。
