クラスにフィールドを持たせる
このレッスンで分かること
- フィールドはクラスの中に書く変数で、インスタンスごとに値を保持します
アクセス修飾子 型 名前;の形で宣言し、obj.fieldでアクセスします- 最小例は
class Book { String title; } ... Book b = new Book(); b.title = "Java";
クラスにフィールドを持たせる とは
クラスにフィールドを持たせて、オブジェクトが「データ」を抱えられるようにする方法を学びます。本レッスンでは、クラスにフィールドを持たせる の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
クラスにデータを持たせる ─ フィールドの正体
前のレッスンで class という箱を作る方法を学びました。ただしあの段階の class は、まだ「空き箱」に近い存在です。中身が空っぽのままでは Book クラスも User クラスも、ただの名前だけの飾りになってしまいます。
ここで登場するのが フィールド (field) です。フィールドとは、クラスの中に書く変数のことで、そのクラスから作られたオブジェクトが「自分のデータ」として持ち続ける値を表します。Book クラスなら「題名」「著者」「ページ数」、User クラスなら「名前」「年齢」「メールアドレス」── こうした情報の置き場所がフィールドです。
フィールドは英語の
field(畑、領域) から来た言葉で、データを耕しておく区画のようなイメージです。C#ではfield、Pythonではattribute、JavaScriptではpropertyと呼びますが、役割はほぼ同じだと思って大丈夫です。
フィールドが書ければ、class はようやく本来のチカラを発揮します。ひとつの設計図 (class) から、それぞれ違うデータを持った複数のオブジェクト (インスタンス) を量産できるようになるからです。たとえば Book クラスがあれば、b1 には『吾輩は猫である』、b2 には『Java 入門』、b3 には Effective Java ── と、同じ型の入れ物にそれぞれ違うタイトルを詰めることができます。
フィールドとは何か
フィールドの定義を一度きちんと整理しておきましょう。フィールドの特徴は次のとおりです。
- クラスの中 (メソッドの外側) に書く変数
- そのクラスから作られたオブジェクトごとに値を保持する (インスタンスフィールド)
- もしくは、クラス全体で 1 個だけ共有する (静的フィールド、
static付き) - 型 (
Stringintbooleanなど) を必ず付ける - アクセス修飾子 (
publicprivateprotected) で見える範囲を制御できる
初心者がよく混乱するのが「メソッドの中で宣言した変数」と「フィールド」の違いです。メソッドの中で String name = "Java"; と書いた name は ローカル変数 で、メソッドを抜けた瞬間に消えます。一方でクラス直下に書いたフィールドは、そのオブジェクトが生きている間ずっと値を覚え続けます。
例えるなら、ローカル変数は「会議室のホワイトボード」、フィールドは「自分の手帳」です。会議が終わればホワイトボードは消されますが、手帳に書いた内容はあとから何度でも読み返せます。
フィールドの宣言文法
フィールドの書き方はとてもシンプルです。「アクセス修飾子 + 型 + 名前 + (初期値) + ;」の順番で書きます。
Java
public class Book {
public String title; // 題名 (String 型)
public String author; // 著者 (String 型)
public int pages; // ページ数 (int 型)
public boolean isAvailable; // 貸出可能か (boolean 型)
}このコードは「Book というクラスには title author pages isAvailable という 4 つのフィールドがある」と宣言しているだけで、まだ実体 (オブジェクト) は作られていません。
初期値を直接書くこともできます。たとえば「初期状態は貸出可能」と決めておきたいなら、宣言と同時に値を渡せます。
Java
public class Book {
public String title = "未設定";
public int pages = 0;
public boolean isAvailable = true;
}初期値を書かなかった場合、Java は型ごとに 既定値 を自動で入れてくれます。
| 型 | 既定値 |
|---|---|
int long short byte | 0 |
double float | 0.0 |
boolean | false |
char | � |
参照型 (String など) | null |
null のままアクセスすると NullPointerException が出るので、String 型のフィールドはなるべく初期化しておくのが安全です。
インスタンスフィールド vs 静的フィールド
フィールドには大きく分けて 2 種類があります。static が付くか付かないかで意味がガラッと変わるので、ここはしっかり押さえておきましょう。
Java
public class Book {
public String title; // インスタンスフィールド
public static int totalCount; // 静的フィールド (クラス全体で 1 個)
}- インスタンスフィールド ── オブジェクトごとに別々の値を持つ。
b1.titleとb2.titleは独立 - 静的フィールド (クラスフィールド) ── クラス全体で 1 個だけ。
Book.totalCountのようにクラス名から直接アクセスする
「世の中に存在する Book の冊数を全部数えたい」なら静的フィールドが便利ですし、「1 冊ごとの題名」を持ちたいならインスタンスフィールドの出番です。迷ったら 「個体差があるか?」 で判断してください。個体差があるならインスタンス、ないなら static です。
staticを付け忘れて全インスタンスで共有させたかった値が個別管理になってしまった、というバグはあるあるです。逆にstaticを付けすぎて、本来は個別に持つべき題名がクラス全体で 1 個になってしまうのも危険です。
アクセス修飾子をやんわり紹介
フィールドの先頭に付く public や private を アクセス修飾子 と呼びます。今は深掘りせず、雰囲気だけ掴んでおきましょう。
public── どこからでも読み書きできる。手軽だが無防備private── そのクラスの内側からしか触れない。データを守る基本姿勢protected── 同じパッケージか、継承したサブクラスからアクセスできる- 修飾子なし (パッケージプライベート) ── 同じパッケージからのみアクセスできる
本格的な現場のコードでは、フィールドはほとんど private にして、getter / setter メソッド経由で操作するのが定石です。これを カプセル化 (encapsulation) と呼びますが、本レッスンでは「まずフィールドを置いてみる」段階なので public で十分です。次のレッスン以降で private への移行を扱います。
Book クラスとフィールドの関係を図にする
ここまでの話を、Book クラスを例にしたクラス図でまとめてみましょう。title author pages の 3 つのフィールドと、それを使うメソッド createBookTitle() の関係を視覚化します。
図の関係を箇条書きで整理すると、次の通りです。
Bookクラスはフィールドtitleauthorpagesを持つSolution.createBookTitle()はBookインスタンスを作成 → 値を設定 → 値を読み出すSolutionはBookを「使う」(依存) 関係 (UML の..>)- フィールドの
+はpublicを示す UML 記号
実際にコードに落とすと、こんなイメージになります。
Java
class Book {
public String title;
}
public class Solution {
public static String createBookTitle() {
Book book = new Book();
book.title = "Java 入門";
return book.title;
}
}new Book() で Book の実体を 1 つ作り、book.title に値を代入、最後に book.title を読み取って return で返しています。設計図 → 実体化 → フィールド書き込み → 読み出し という、オブジェクト指向の基本的な 4 ステップが詰まったコードです。
よくある間違い
フィールドを書き始めると、多くの初心者が同じ場所でつまずきます。代表的な落とし穴を 3 つ紹介します。
- アクセス修飾子を書き忘れる ── 修飾子なしで
String title;と書くと「パッケージプライベート」になります。最初のうちはpublicを明示的に書きましょう staticの付け間違い ── インスタンスフィールドにすべき題名にstaticを付けてしまうと、全Bookオブジェクトでタイトルが共有されてしまいます- 初期化を忘れて
NullPointerException──String title;のままbook.title.length()を呼ぶとnullに対してメソッドを呼ぶことになり、実行時にクラッシュします
もうひとつ地味に多いミスが、フィールドとローカル変数の名前衝突 です。メソッドの引数に title と書きつつ、フィールドにも title がある場合、何もしないと「引数の title」が優先されてフィールドが書き換わらないという罠が発生します。これは将来 this.title = title; という書き方で解決しますが、今は「同じ名前を使わない」だけで十分です。
エラーメッセージで
variable might not have been initializedと出たら、フィールドではなくローカル変数の初期化忘れがほとんどです。
ここまでの要点
フィールドはクラスの中に書く変数。インスタンスフィールドはオブジェクトごと、static はクラス全体。null 参照のフィールドアクセスは NullPointerException。
やってみよう
それでは、このレッスンの課題に挑戦しましょう。題材は 「引数で受け取った文字列を Book.title に書き込み、それを読み出して返す」 というものです。固定の文字列を即 return するのは禁止です。必ずフィールドを経由してください。
- 右側のエディタで
Solution.createBookTitle(String title)を開く new Book()でインスタンスを作るbook.title = title;のようにフィールドへ代入するreturn book.title;で読み出した値を返す
Book クラスはすでに static class Book { ... } として Solution の中に用意してあります。フィールド title author pages の宣言はそのままで構いません。
慣れてきたら book.author や book.pages にも値を入れて、title + " / " + author のような形に describe() 風メソッドを書き足してみてください。次のレッスンで扱う インスタンスメソッド の予習になります。
次のレッスン
次は クラスにメソッドを定義する で、クラスにフィールドを持たせて、オブジェクトが「データ」を抱えられるようにする方法を学びます を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- フィールド の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. フィールド とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
createBookTitleの中でnew Book()を使ってインスタンスを作ることbook.titleフィールドに引数titleを代入してからreturnすること (固定文字列の即時 return は不可)- 戻り値はそのインスタンスの
titleフィールドの値であること
入出力例
test-cases.txt
createBookTitle("Java 入門") → "Java 入門"
createBookTitle("Effective Java") → "Effective Java"
createBookTitle("") → ""