まずは問題を見ろ
→ javadrill.tech で出題された問題を見る(Step06)
問題のポイント
static { ... }
は、クラスが初めて使われたときに一度だけ実行される初期化処理static
変数の複雑な初期化や、一括設定処理に使われる- インスタンス化とは無関係に動く「一回限りのブート処理」
まず、日本語で考えろ
- アプリを起動したら、設定値を1回だけ読み込みたい
- 毎回newされるのは困る。設定は1つでいい
static
変数に値を入れる必要があるが、定数ではなく実行時の値(例:時刻)も含まれる- そんなとき、static初期化ブロックが活躍する
コメントを書け
// AppConfigクラスを定義
// static変数:VERSION, DEBUG_MODE, LOADED_AT を定義
// static初期化ブロックの中で一括初期化
// printConfig() で設定内容を出力
コメントに従って、コードを書け
import java.time.LocalDateTime;
public class AppConfig {
public static String VERSION;
public static boolean DEBUG_MODE;
public static LocalDateTime LOADED_AT;
static {
VERSION = "1.0.0";
DEBUG_MODE = true;
LOADED_AT = LocalDateTime.now();
}
public static void printConfig() {
System.out.println("App Config:");
System.out.println("VERSION: " + VERSION);
System.out.println("DEBUG_MODE: " + DEBUG_MODE);
System.out.println("LOADED_AT: " + LOADED_AT);
}
}
public class Main {
public static void main(String[] args) {
AppConfig.printConfig();
}
}
コードの解説
static
変数が複数あるときや、実行時の値で初期化する必要があるときに staticブロックは便利static
メソッドや変数に初めてアクセスしたとき、ブロックが一度だけ実行される- このブロックの中でまとめて初期化すれば、設定漏れや初期化順序の問題を防げる
つまづきやすいポイント
- コンストラクタとの違いが曖昧になりがち:
static {}
は new しなくても動く static
変数の初期化に= 値;
を書くより、複雑なロジックなら staticブロックでまとめた方が安全AppConfig
のような「設定クラス」は、staticブロックと相性が良い
// tesh:
// アプリってのはな、「最初に全部決める」ことで安定すんねん。
// 起動するたびに設定バラバラ、環境によって動きが変わる──そんなもん、現場には要らん。
//
// そこで出てくるのが static {} ってわけや。
// これはいわば、「クラスが初めて呼ばれた瞬間に、一回だけ動く 自己紹介」や。
//
// 例えば AppConfig。new せずとも printConfig() を叩いた時点で、
// VERSION、DEBUG_MODE、LOADED_AT がバチッと初期化されとる。
// しかも、その一回きり。
//
// それがええんや。設定ってのは「最初に1回決めるから意味がある」。
// 起動のたびに new して setXXX() とかしてたら、どっかでミスる。バグる。信用できん。
//
// 設計の本質ってのは「ミスれない設計」にすることや。
// static {} は、“準備し忘れを許さないブロック” なんや。
//
// しかもこの初期化、コンストラクタとは独立してる。
// だから new を強制せんでええ。「最初の一発だけ、自動で走るコード」。
//
// 複雑な初期化が必要? そしたら static {} に書け。
// 定数じゃ足りん? 実行時の値を突っ込め。
//
// 「ああ、最初に全部決めてくれてるな」って、後から見たやつが安心する構造。
// それが設計やろ。