1. クラスのフィールド: オブジェクトの状態はどこに保存するか
フィールドとは、クラスの内部で宣言されるが、すべてのメソッドの外側にある変数のことです。フィールドは、各オブジェクトがそれぞれの「状態」を持てるようにします。たとえば、クラス Person があるなら、フィールドは次のようになります:
- name — 人の名前
- age — 年齢
- balance — 口座残高(銀行アプリを作っている想定なら)
- isStudent — 学生かどうかを表すフラグ
フィールド宣言の構文
フィールドの宣言は通常の変数に似ていますが、メソッドの中ではなくクラス本体に置きます:
public class Person {
String name;
int age;
}
ここでは 2 つのフィールド、文字列の name と整数の age を宣言しました。各フィールドはこのクラスの各オブジェクトに属します。つまり、異なるオブジェクトはそれぞれ独自の値を持ちます。例:
Person p1 = new Person();
p1.name = "Olya";
p1.age = 20;
Person p2 = new Person();
p2.name = "Igor’";
p2.age = 25;
最初のオブジェクトの名前は「Olya」、年齢は 20。2 つ目は「Igor’」で 25。どちらも同じクラスから作られていますが、各フィールドに保持されるデータは異なります。
アクセス修飾子(public/private)
フィールドは公開(public)にも非公開(private)にもできます。現実世界でも銀行口座の残高を誰にでも教えたりはしませんよね。プログラミングでも、他のクラスから直接アクセスされないようにフィールドを private にするのが一般的です。これはカプセル化という原則の一部です(詳細は次回)。
例:
public class Person {
private String name;
private int age;
}
いまは深入りしませんが、覚えておきましょう: フィールドが private の場合、他のクラスから直接参照することはできません。
2. クラスのメソッド: オブジェクトはどのように「振る舞う」か
メソッドは、オブジェクトの振る舞いを記述する関数です。メソッドによって、話す、計算する、走る、跳ぶ、自分の情報を表示する、などの動作を実現できます。
メソッド宣言の構文
tip_vozvrashchaemogo_znacheniya imyaMetoda(parametry) {
// メソッド本体
}
「こんにちは」と話すメソッドの例:
public void sayHello() {
System.out.println("こんにちは! 私の名前は " + name);
}
ここでは:
- public — アクセス修飾子。
- void — 何も値を返しません(処理だけを行います)。
- sayHello — メソッド名。
- メソッド内部でフィールド name を使って挨拶文を作っています。
もう一つの例: 年齢を返すメソッド
public int getAge() {
return age;
}
メソッドは値(int、String など)を返すこともあれば、何も返さないこともあります。その場合は void と書きます。
3. コンストラクタ: オブジェクトはどうやって「生まれる」のか
コンストラクタは、新しいオブジェクトの生成時に呼び出される特別なメソッドです。役割はオブジェクトのフィールドを初期値で初期化すること、つまりオブジェクトの「空のポケット」を具体的なデータで埋めることです。たとえば、人の名前と年齢を生成の瞬間に与える、といった具合です。
- コンストラクタ名はクラス名と常に一致します。
- コンストラクタには戻り値の型がありません(void すら書きません)。
- コンストラクタは引数を取ることも(たとえば名前と年齢)、取らないこともあります。
コンストラクタの例
public class Person {
String name;
int age;
// 2 つの引数を取るコンストラクタ
public Person(String name, int age) {
this.name = name; // this.name はオブジェクトのフィールド、name はコンストラクタの引数
this.age = age;
}
}
ここで気になるのが this です。キーワード this は「現在のオブジェクト」への参照を指します(オブジェクトの内側から見た自分自身)。クラスのフィールドと、同じ名前の引数を区別するために使います。this がなければ、どちらを初期化したいのかコンパイラが混乱してしまいます。
デフォルトコンストラクタ
コンストラクタを一つも宣言しなかった場合、Java コンパイラは自動的に引数なしの空のコンストラクタを追加します。見た目は次のとおりです:
public Person() {
// 何もしないが、引数なしでオブジェクトを作成できる
}
ただし! もし引数付きのコンストラクタなどを 1 つでも宣言したら、デフォルトコンストラクタは自動生成されなくなります。必要なら明示的に書きましょう。
4. 完全なクラスの例
フィールド、メソッド、コンストラクタをすべてまとめてみましょう。
public class Person {
String name;
int age;
// コンストラクタ
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// メソッド: あいさつする
public void sayHello() {
System.out.println("こんにちは! 私の名前は " + name + "、私は " + age + " 歳です。");
}
// メソッド: 年齢を 1 増やす
public void haveBirthday() {
age = age + 1;
System.out.println("やった! 今は " + age + " 歳だ!");
}
}
プログラムでどのように使うのか?
public class Main {
public static void main(String[] args) {
Person vasya = new Person("Vasya", 18);
vasya.sayHello(); // こんにちは! 私の名前は Vasya、私は 18 歳です。
vasya.haveBirthday(); // やった! 今は 19 歳だ!
}
}
5. 実践: 自分のアプリを発展させよう
たとえば、簡単なユーザー管理アプリを作っているとします。前回までは main の中の変数とメソッドだけを使っていました。ここではフィールド、メソッド、コンストラクタを持つ自分のクラス User を作成します。
public class User {
String username;
int score;
// コンストラクタ
public User(String username, int score) {
this.username = username;
this.score = score;
}
// メソッド: ユーザー情報を表示
public void printInfo() {
System.out.println("ユーザー名: " + username + "、スコア: " + score);
}
// メソッド: スコアを増やす
public void addScore(int points) {
score += points;
System.out.println(username + " は " + points + " ポイントを獲得! 現在は " + score + " ポイントです。");
}
}
使用例:
public class Main {
public static void main(String[] args) {
User alice = new User("Alice", 10);
User bob = new User("Bob", 5);
alice.printInfo(); // ユーザー名: Alice、スコア: 10
bob.printInfo(); // ユーザー名: Bob、スコア: 5
alice.addScore(7); // Alice は 7 ポイントを獲得! 現在は 17 ポイントです。
bob.addScore(3); // Bob は 3 ポイントを獲得! 現在は 8 ポイントです。
}
}
注意: 各オブジェクトは自分専用のフィールドを持ち、あるオブジェクトの変更は別のオブジェクトに影響しません。
6. アクセス修飾子の概要
ここまでの例ではフィールドは公開(String name;)でした。実際には、他のクラスからうっかり(あるいは意図的に)変更されないように、フィールドを private にすることがよくあります。詳しくはカプセル化の章で扱いますが、次が例です:
public class User {
private String username;
private int score;
public User(String username, int score) {
this.username = username;
this.score = score;
}
public void printInfo() {
System.out.println("ユーザー名: " + username + "、スコア: " + score);
}
public void addScore(int points) {
score += points;
}
}
これで、誰かがクラスの外で alice.score = 100500; と書こうとすると、コンパイラに「ダメです!」と言われます。
7. フィールド、メソッド、コンストラクタでよくあるミス
エラー1: フィールドの未初期化。
フィールドに値を設定しないと、デフォルト値が入ります。数値は 0、boolean は false、参照(たとえば String)は null です。初期化を忘れると、思わぬ結果になったり、操作時に NullPointerException が発生することがあります。
エラー2: パラメータとフィールドの取り違え。
コンストラクタで、初心者がよく name = name; のように書いてしまいますが、これはフィールドの初期化ではなく、引数に引数を代入しているだけです。必ず this.name = name を使いましょう!
エラー3: デフォルトコンストラクタがない。
引数付きのコンストラクタを宣言したのに、空のコンストラクタを明示的に追加し忘れると、new Person() は使えません。
エラー4: メソッド名とクラス名を同じにしてしまう。
Java ではコンストラクタ名はクラス名と一致しなければなりませんが、メソッド名は一致していてはいけません。誤ってメソッドにクラスと同じ名前を付けると、コンパイラに怒られます。
エラー5: アクセス修飾子を忘れる。
フィールドを public にしてしまうと、どこからでも変更できてしまい、大規模なプログラムでは危険です。最初から private に慣れ、アクセスにはメソッドを使うようにしましょう。
GO TO FULL VERSION