012-001-009
static変数でインスタンス数をカウント
上級
問題説明
static変数: クラスレベルの共有状態
static変数はインスタンスではなくクラス自体に属します。すべてのインスタンスが同じstatic変数を共有するため、インスタンスのカウント、データのキャッシュ、すべてのオブジェクト間で共有される設定の保存に最適です。
一緒にstatic変数の仕組みを理解していきましょう。
学習目標
- static変数を用いてクラス全体でインスタンス数を追跡する仕組みを設計できる
- コンストラクタ内でstatic変数を更新することで、オブジェクト生成時の状態管理システムを構築できる
- static変数とインスタンス変数の適切な使い分けを評価し、クラス設計に統合できる
学習ポイント
- staticキーワード: メンバーをインスタンスレベルではなくクラスレベルとしてマーク
- 共有状態: すべてのインスタンスで1つのコピーを共有
- クラスロード: クラスが最初にロードされた時に初期化
- アクセスパターン: クラス名.メンバー または インスタンス.メンバー(クラス推奨)
static vs インスタンス変数
| 観点 | static変数 | インスタンス変数 |
|---|---|---|
| 所属先 | クラス | オブジェクトインスタンス |
| コピー数 | クラスごとに1つ | インスタンスごとに1つ |
| 寿命 | クラスロードからアンロードまで | オブジェクト作成からGCまで |
| アクセス | クラス名.変数 | インスタンス.変数 |
| メモリ | メソッド領域 | ヒープ |
よくある間違い
間違いを見つけたら、もう一度static変数とインスタンス変数の違いを確認してみましょう。
間違い1: staticコンテキストからインスタンスメンバーにアクセス
コンパイルエラー:
class Counter {
private String name; // インスタンス変数
public static void printName() {
System.out.println(name); // エラー!アクセス不可
}
}正しいコード:
public static void printCount() {
System.out.println(count); // OK - staticはstaticにアクセス可
}間違い2: スレッドセーフティの問題
競合状態:
private static int count = 0;
public Counter() {
count++; // マルチスレッドアプリではスレッドセーフでない!
}スレッドセーフ版:
private static AtomicInteger count = new AtomicInteger(0);
public Counter() {
count.incrementAndGet(); // スレッドセーフ
}実務での応用
- シングルトンパターン: staticフィールドに単一インスタンスを保存
- カウンター/ID: インスタンス間で一意のIDを生成
- キャッシュ: すべてのインスタンスがアクセスする共有キャッシュ
- 設定: アプリ全体の設定
設計のガイドライン
- staticは控えめに使用 - インスタンス状態を優先
- static変数は可能な限りfinalにする
- 並行アプリケーションではスレッドセーフティを考慮
- 共有状態を明確にドキュメント化
前提知識の詳細説明
この問題を解くために必要な知識を確認しましょう。
基本概念
この問題で扱うプログラミングの基本概念を理解することが、正しい解答への第一歩です。コードの各要素がどのように連携して動作するかを把握しましょう。
実装アプローチ
問題を解くための考え方を段階的に整理します:
- 問題文を読み、入力と出力の関係を理解する
- 必要な変数やデータ構造を特定する
- 処理の流れを組み立てる
- テストケースで動作を確認する
