static 修飾的成員(變數、方法、區塊、內部類別)屬於類別本身,不依賴任何具體實例即可存取。JVM 在類別載入階段於方法區分配記憶體,所有實例共享同一份靜態資料。
public class Counter {
private static int count = 0; // 靜態變數
private int instanceCount = 0; // 實例變數
public Counter() {
count++;
instanceCount++;
}
public static int getCount() { return count; }
public int getInstanceCount() { return instanceCount; }
}
類別名.靜態變數 存取(推薦),亦可透過實例存取(不推薦,編譯器會警告)private static 限制外部類別直接存取,僅允許本類別靜態方法/區塊使用public class MathUtils {
public static int add(int a, int b) { return a + b; }
// 編譯錯誤:靜態方法無法存取 this/super
// public static void printInstance() { System.out.println(this); }
}
限制:無法直接呼叫非靜態成員、無法使用 this/super、不能宣告為 abstract(因為靜態方法屬於類別,無法被覆寫,只能被隱藏)。
public class DatabaseConfig {
private static String URL;
private static Connection POOL;
static {
// 類別載入時執行,按出現順序依序執行
try {
URL = "jdbc:mysql://localhost:3306/mydb";
POOL = DriverManager.getConnection(URL, "user", "pass");
System.out.println("資料庫連線池初始化完成");
} catch (SQLException e) {
throw new ExceptionInInitializerError(e);
}
}
}
ExceptionInInitializerError
public class Outer {
private static String config = "CFG";
static class Nested {
void print() { System.out.println(config); } // 可存取外部類別靜態成員
}
}
靜態內部類別不持有外部類別實例參考,適合實作單例模式、建構者模式等。
public class Constants {
public static final double PI = 3.14159; // 編譯期常數,內聯優化
public static final List IMMUTABLE_LIST = // 執行期不可變集合
Collections.unmodifiableList(Arrays.asList("A", "B", "C"));
}
static 變數儲存在堆區的類別物件中(JDK 8 移除 PermGen,改用 Metaspace)。多執行緒存取靜態變數時,需注意:
volatile 保證可見性與禁止指令重排AtomicInteger 等原子類別提供無鎖執行緒安全操作volatile