インスタンス変数 vs 静的変数
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 15/87。
これまで、作成したすべてのフィールドは特定のオブジェクトに属していました。各 BankAccount は独自の balance を持ち、各 Product は独自の name を持っています。これらは インスタンス変数 であり、クラスのインスタンスごとに個別に存在します。
しかし、すべてのオブジェクトで共有されるデータが必要な場合はどうすればよいでしょうか?そこで登場するのが静的変数(クラス変数とも呼ばれます)です。静的変数は、特定のオブジェクトではなく、クラス自体に属します。
public class Student {
private String name; // インスタンス変数 - 各学生に固有
private static int totalCount; // 静い変数 - すべての学生で共有
public Student(String name) {
this.name = name;
totalCount++; // 共有カウンターをインクリメント
}
public static int getTotalCount() {
return totalCount;
}
}複数の学生を作成すると、それぞれが独自の name を持ちますが、すべてが同じ totalCount を共有します:
Student s1 = new Student("Alice");
Student s2 = new Student("Bob");
System.out.println(Student.getTotalCount()); // 出力: 2オブジェクトを通じてではなく、クラス名(Student.getTotalCount())を通じて静的変数にアクセスしていることに注目してください。これは、静的メンバーがインスタンスではなくクラスに属していることを強調しています。
オブジェクト間で異なるデータ(生徒の名前など)にはインスタンス変数を使用します。共有すべきデータ(存在するオブジェクトの数をカウントするなど)には静的変数を使用します。
チャレンジ
簡単インスタンス変数と static 変数を使用して、個々の本の詳細とコレクション全体の合計冊数の両方を追跡する Book 在庫システムを構築しましょう。
コードを整理するために 2 つのファイルを作成します。
Book.java: 個々の本の情報を追跡しながら、これまでに作成されたすべての本の合計数をカウントする Book クラスを作成します。- インスタンス変数
title(String) - 各本に固有 - インスタンス変数
price(double) - 各本に固有 - static 変数
totalBooks(int) - すべての Book オブジェクトで共有され、作成された本の数を追跡します - タイトルと価格を受け取り、本の総数をインクリメントするコンストラクタ
- タイトルのためのゲッター
getTitle() - 価格のためのゲッター
getPrice() - 作成された本の総数を返す static メソッド
getTotalBooks()
- インスタンス変数
Main.java: 複数の Book オブジェクトを作成し、static カウンタがすべてのインスタンスをどのように追跡するかを示します。入力として 3 つの本のタイトルと 3 つの価格を受け取ります。3 つの本をすべて作成した後、4 行出力してください。- 各本のタイトルと価格を次の形式で出力します:
[title]: $[price](価格は小数点以下 2 桁にフォーマット) - static メソッドを使用した本の総数:
Total books: [count]
- 各本のタイトルと価格を次の形式で出力します:
title1, price1, title2, price2, title3, price3 の順に 6 つの入力を受け取ります。
static メソッドには、オブジェクトのインスタンス経由ではなく、クラス名 (Book.getTotalBooks()) を通じてアクセスすることを忘れないでください。価格のフォーマットには、String.format("%.2f", price) を使用してください。
チートシート
静的変数(クラス変数とも呼ばれます)は、クラス自体に属し、そのクラスのすべてのインスタンス間で共有されます。各オブジェクトに固有のインスタンス変数とは異なります。
staticキーワードを使用して静的変数を宣言します:
public class Student {
private String name; // インスタンス変数 - 各学生に固有
private static int totalCount; // 静的変数 - すべての学生で共有
public Student(String name) {
this.name = name;
totalCount++; // 共有カウンターをインクリメントします
}
public static int getTotalCount() {
return totalCount;
}
}静的変数やメソッドには、オブジェクトのインスタンス経由ではなく、クラス名を通じてアクセスします:
Student s1 = new Student("Alice");
Student s2 = new Student("Bob");
System.out.println(Student.getTotalCount()); // 出力: 2オブジェクトごとに異なるデータにはインスタンス変数を使用します。すべてのインスタンス間で共有すべきデータには静的変数を使用します。
自分で試してみよう
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 3冊の本の入力を読み込む
String title1 = scanner.nextLine();
double price1 = Double.parseDouble(scanner.nextLine());
String title2 = scanner.nextLine();
double price2 = Double.parseDouble(scanner.nextLine());
String title3 = scanner.nextLine();
double price3 = Double.parseDouble(scanner.nextLine());
// TODO: 上記の入力を使用して3つの Book オブジェクトを作成する
// TODO: 各本のタイトルと価格を [title]: $[price] の形式で出力する
// 価格を小数点以下2桁にフォーマットするために String.format("%.2f", price) を使用する
// TODO: static メソッドを使用して本の総数を出力する
// 形式: Total books: [count]
// クラス名を通じて static メソッドにアクセスすることを忘れないでください: Book.getTotalBooks()
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造