static 是 Java 中最基礎也最容易被誤解的關鍵字之一。它不僅是日常開發的高頻工具,更是大廠面試的必考知識點。本文將從核心用法、常見誤區、經典面試題三個維度,為你構建完整的 static 知識體系。
核心定位: static 修飾的成員(變量/方法)屬於類而非對象。只要類被加載,即可透過類名直接訪問,無需創建實例。
this 或 super。Collections.sort())、單例模式獲取實例、main 入口方法。public class MyObject {
static String str2 = "靜態變量";
String str1 = "非靜態變量";
static void print2() { System.out.println(str2); } // OK
// static void print1() { System.out.println(str1); } // 編譯錯誤:靜態方法訪問非靜態變量
void print1() { print2(); } // 非靜態方法訪問靜態方法:OK
}
// 優化前:每次調用創建對象
boolean isBornBoomer() {
Date start = Date.valueOf("1946"); // 重複創建
Date end = Date.valueOf("1964");
return birthDate.compareTo(start) >= 0 && birthDate.compareTo(end) < 0;
}
// 優化後:靜態塊初始化一次
private static Date START, END;
static {
START = Date.valueOf("1946");
END = Date.valueOf("1964");
}
boolean isBornBoomer() {
return birthDate.compareTo(START) >= 0 && birthDate.compareTo(END) < 0;
}
錯誤觀點: 混淆了 C/C++ 中 static 限制作用域的特性。
事實: Java 中 static 完全不影響 訪問權限。權限控制僅由 private、protected、public、包私有決定。
class Person { static int age = 10; }
class Test { void test() { System.out.println(Person.age); } } // 若 age 為 private,這裡報錯 "不可見",證明 static 不改權限
結論: 可以。this 代表當前對象,靜態變量雖屬於類,但對象同樣持有訪問路徑。
關鍵點: 方法內的同名局部變量不屬於 this,this.value 永遠訪問的是靜態/實例字段。
public class Main {
static int value = 33;
void printValue() { int value = 3; System.out.println(this.value); } // 輸出 33
}
絕對不能。 Java 語法規定 static 僅能修飾類成員(字段、方法、內部類、代碼塊),不能用於方法內部的局部變量。這與 C/C++ 不同。
public class Test extends Base {
static { System.out.println("test static"); }
public Test() { System.out.println("test constructor"); }
public static void main(String[] args) { new Test(); }
}
class Base {
static { System.out.println("base static"); }
public Base() { System.out.println("base constructor"); }
}
輸出:
base static
test static
base constructor
test constructor
解析: JVM 加載 Test 發現繼承 Base → 先加載 Base 執行其靜態塊 → 加載 Test 執行其靜態塊 → main 執行 new Test() → 調用父構造器 → 調用子構造器。
public class Test {
Person person = new Person("Test"); // 實例變量初始化
static { System.out.println("test static"); }
public Test() { System.out.println("test constructor"); }
public static void main(String[] args) { new MyClass(); }
}
class Person {
static { System.out.println("person static"); }
public Person(String str) { System.out.println("person " + str); }
}
class MyClass extends Test {
Person person = new Person("MyClass");
static { System.out.println("myclass static"); }
public MyClass() { System.out.println("myclass constructor"); }
}
輸出:
test static
person static
person Test
myclass static
person MyClass
test constructor
myclass constructor
關鍵: 靜態塊按類加載順序執行(父類→子類);實例變量初始化和構造器在 new 時執行,順序為:父類實例變量 → 父構造器 → 子類實例變量 → 子構造器。
掌握 static 的本質是「屬於類、共享、早綁定」,理解其與 this、訪問權限、初始化順序的交互細節,即可輕鬆應對開發與面試。記住:靜態屬於類,動態屬於對象;靜態先行,動態隨行。