static 本質
static 表示「屬於類別,不屬於實例」。JVM 類別載入時,在方法區分配記憶體,全進程僅一份,所有實例共享。
靜態變數(類別變數)
| 特性 | 靜態變數 | 實例變數 |
| 記憶體份數 | 一份(方法區) | 每實例一份(堆) |
| 初始化時機 | 類別載入時 | 建立實例時 |
| 存取方式 | ClassName.field(推薦)或 obj.field(不推薦) | obj.field |
| 生命週期 | 類別卸載時結束 | 實例 GC 時結束 |
適用場景
- 全域共享狀態(計數器、快取、單例)。
- 常數定義(配合
final)。
靜態方法
- 直接
ClassName.method() 呼叫,無需實例。
- 限制:不可使用
this/super、不可直接存取實例成員、不可為 abstract(因無多型)。
- 典型用途:工具方法(
Math.*)、工廠方法、單例 getInstance()。
靜態初始化區塊
class Demo {
static int a;
static {
a = 3;
System.out.println("Static block 1: " + a); // 3
}
static {
a = 4;
System.out.println("Static block 2: " + a); // 4
}
}
- 類別載入時按宣告順序依序執行,僅執行一次。
- 用於複雜靜態變數初始化(讀取配置、註冊驅動、建立查找表)。
- 可建立實例並呼叫實例方法(如單例初始化)。
static + final:編譯期常數
public static final double PI = 3.14159;
public static final String CONFIG_PATH = "/etc/app.conf";
- 變數:編譯期常數折疊,調用端會內聯常數值(修改需重編譯調用端)。
- 方法:不可覆寫(隱含 final),可靜態呼叫。
- 命名慣例:全大寫底線分隔。
記憶體模型圖解
[方法區] ← static 變數、方法、常數池、類別元資料
↑
[堆] ← 實例物件、實例變數
↑
[棧] ← 區域變數、方法呼叫框架
常見誤區與最佳實踐
- 靜態方法呼叫實例方法 → 編譯錯誤。若需共用邏輯,提煉為靜態工具方法或傳入實例參數。
- 多執行緒下靜態可變狀態 → 競態條件。用
AtomicInteger、ConcurrentHashMap、synchronized 或 ThreadLocal。
- 單例雙重檢查鎖 → 必須加
volatile 防止指令重排。
- 靜態導入濫用 → 降低可讀性,僅對常數/常用工具方法使用。
static 是打破物件封裝的「後門」,功能強大但耦合度高。慎用可變 static,善用 static final 定義契約。
- 上一篇文章: Java 排序大全:Arrays.sort、Collections.sort、Comparable 與 Comparator 完全指南
- 下一篇文章: Java 編碼 30 條軍規:從命名到架構的實戰精華
Copyright ©
程式碼之家 All Rights Reserved