1. 爲什麼需要static關鍵字?¶
我們先想一個場景:如果有一個Student類,每個學生有自己的名字和年齡(這些是每個學生獨立的信息),但我們還需要統計總共有多少個學生(這是所有學生共享的信息)。如果不用static,每個學生對象都要單獨存一個總人數變量,這會浪費內存且容易出錯。這時static關鍵字就派上用場了——它可以讓變量和方法屬於類,而不是某個具體對象,實現數據共享。
2. 靜態變量(類變量)¶
定義:用static修飾的變量稱爲靜態變量(類變量),它屬於整個類,所有通過該類創建的對象共享同一個靜態變量的存儲空間。
特點:
- 所有對象共享一份靜態變量,修改一個對象的靜態變量會影響所有對象。
- 可通過類名直接訪問(推薦),也可通過對象訪問(不推薦,易混淆)。
- 靜態變量在類加載時初始化,生命週期與類相同(JVM關閉時銷燬)。
例子:用Student類統計總人數
class Student {
// 實例變量:每個學生獨立(姓名、年齡)
String name;
int age;
// 靜態變量:所有學生共享(統計總人數)
static int totalStudents = 0;
// 構造方法:創建學生對象時,總人數+1
public Student(String name, int age) {
this.name = name;
this.age = age;
totalStudents++; // 每次創建對象,總人數累加
}
// 打印學生信息(實例方法)
public void showInfo() {
System.out.println("姓名:" + name + ",年齡:" + age);
}
}
public class TestStudent {
public static void main(String[] args) {
Student stu1 = new Student("張三", 20);
Student stu2 = new Student("李四", 21);
// 通過類名訪問靜態變量(推薦)
System.out.println("總學生數:" + Student.totalStudents); // 輸出:2
stu1.showInfo(); // 輸出:姓名:張三,年齡:20
stu2.showInfo(); // 輸出:姓名:李四,年齡:21
}
}
3. 靜態方法(類方法)¶
定義:用static修飾的方法稱爲靜態方法(類方法),屬於整個類,無需創建對象即可直接調用。
特點:
- 只能訪問靜態成員(靜態變量/靜態方法),不能直接訪問實例成員。
- 可通過類名直接調用(推薦),也可通過對象調用(不推薦)。
- 靜態方法中無this或super(因靜態方法屬於類,對象可能未創建)。
例子:工具類的靜態方法(如日期格式化)
class DateUtils {
// 靜態方法:格式化日期字符串
public static String formatDate(String dateStr) {
// 簡單示例:將"2023-10-01"轉爲"2023年10月01日"
return dateStr.replace("-", "年") + "日";
}
}
public class TestDateUtils {
public static void main(String[] args) {
// 直接通過類名調用靜態方法,無需創建對象
String formatted = DateUtils.formatDate("2023-10-01");
System.out.println(formatted); // 輸出:2023年10月01日
}
}
4. 靜態 vs 實例成員:核心區別¶
| 類型 | 靜態成員(static) | 實例成員(無static) |
|---|---|---|
| 歸屬 | 屬於類,所有對象共享 | 屬於對象,每個對象獨立一份 |
| 訪問方式 | 類名直接訪問 | 通過對象訪問 |
| 生命週期 | 類加載時初始化,類卸載時銷燬 | 對象創建時初始化,對象銷燬時釋放 |
| 訪問範圍 | 只能訪問靜態成員 | 可訪問靜態和實例成員 |
5. 靜態代碼塊¶
若需在類加載時執行初始化操作(如初始化靜態變量),可使用靜態代碼塊(static {})。靜態代碼塊在類加載時執行,且僅執行一次。
例子:初始化靜態變量
class Config {
static String version; // 靜態變量
// 靜態代碼塊:類加載時執行,初始化version
static {
version = "1.0.0";
System.out.println("靜態代碼塊執行:初始化版本號爲" + version);
}
}
public class TestConfig {
public static void main(String[] args) {
System.out.println("獲取版本號:" + Config.version); // 輸出:獲取版本號:1.0.0
System.out.println("再次獲取版本號:" + Config.version); // 靜態代碼塊僅執行一次
}
}
6. 常見問題¶
-
Q:靜態方法爲什麼不能用this?
A:this指向當前對象,但靜態方法屬於類,對象可能未創建(如直接調用Student.getTotalStudents()),因此無this。 -
Q:靜態變量和實例變量可以同名嗎?
A:可以,但不推薦。通過對象訪問時優先實例變量,通過類名訪問時才訪問靜態變量。 -
Q:靜態方法可以被繼承嗎?
A:可以,但子類靜態方法會“隱藏”父類靜態方法(與實例方法重寫不同)。
總結¶
static關鍵字的核心是讓成員屬於類而非對象,主要用於:
- 實現數據共享(如統計類實例數量);
- 提供工具化方法(如工具類的靜態方法);
- 類加載時的初始化操作(靜態代碼塊)。
初學者需重點區分靜態與實例成員的訪問規則,掌握其使用場景即可高效編寫Java代碼。