static 是 Java 中最基礎也最易混淆的關鍵字之一,既是面試高頻考點,也是日常開發中靜態工具類、單例模式、常量定義的基石。本文系統梳理其三大用途、三大誤區,並附三道經典面試題深度解析。
| 誤區 | 錯誤認知 | 正確理解 |
|---|---|---|
| 1. 影響訪問權限 | 以為 static 等同 C/C++ 的文件級私有 | Java 中 static **不改變** `public/protected/private` 訪問權限 |
| 2. this 不能訪問靜態成員 | 以為靜態屬於類,this 代表實例,兩者互斥 | 實例**可以**通過 `this.靜態變數` 訪問,編譯器會轉為 `類名.靜態變數` |
| 3. 可修飾局部變數 | 習慣 C/C++ static int i 在函數內保持狀態 | Java **禁止** 在方法內使用 static 修飾局部變數,編譯報錯 |
class Base { static { System.out.println("base static"); } }
class Sub extends Base {
static { System.out.println("sub static"); }
public static void main(String[] args) { new Sub(); }
}
輸出:
base static sub static
解析:JVM 加載 `Sub` 發現繼承 `Base`,先遞歸加載 `Base` → 執行 `Base` 靜態塊 → 返回執行 `Sub` 靜態塊 → 執行 `main` → `new Sub()` 觸發構造器鏈(父構造器 → 子構造器)。**靜態塊隨類加載一次,與實例化無關**。
class Test {
Person p = new Person("Test"); // ① 實例變數
static { System.out.println("test static 1"); } // ② 靜態塊1
public static void main(String[] args) { new MyClass(); } // 入口
static { System.out.println("test static 2"); } // ③ 靜態塊2
}
class MyClass extends Test {
Person p = new Person("MyClass"); // ④
static { System.out.println("myclass static"); } // ⑤
}
class Person {
static { System.out.println("person static"); }
public Person(String s) { System.out.println("person " + s); }
}
輸出順序:
test static 1 test static 2 myclass static person static person Test person MyClass
關鍵點:
public class Test {
static { System.out.println("static 1"); }
public static void main(String[] args) { }
static { System.out.println("static 2"); }
}
輸出:
static 1 static 2
原因:JVM 啟動需加載主類,加載過程執行所有靜態塊,**與 main 方法體是否有語句無關**。
掌握 static 的「類級屬性、無 this、加載時機」三大核心特性,辨清 C/C++ 差異與訪問權限誤區,配合類加載順序推導,即可輕鬆應對面試與實戰中的靜態陷阱。