| 維度 | 成員變量 (Field) | 局部變量 (Local Variable) |
|---|---|---|
| 聲明位置 | 類體中、方法體外 | 方法體內、構造器、代碼塊、for/while 循環頭部 |
| 作用域 | 整個類(受訪問修飾符限制) | 從聲明處到所在塊結束 |
| 默認值 | 有(數值 0、布爾 false、引用 null) | 無,必須顯式初始化後才能使用 |
| 內存分配 | 堆 — 隨對象創建 | 棧 — 隨方法調用入棧 |
| 生命週期 | 與對象同在(GC 前) | 隨方法調用結束銷毀 |
| 修飾符 | 可用 public/protected/private/static/final/transient/volatile 等 | 僅可用 final(或註解) |
| 線程安全 | 非 final 非 volatile 多線程可見性需同步 | 天然線程封閉,安全 |
ClassLoader)按聲明順序分配內存、賦默認值。static {} 塊),按源代碼順序。
public class Demo {
static int a = 1; // 1. 默認 0 → 2. 賦 1
static int b; // 1. 默認 0
static { b = a + 1; } // 3. 執行 static 塊,b=2
static int c = b + 1; // 4. c=3
}
new)在堆分配內存,賦默認值。{} 塊),按順序。
3. 執行構造器體代碼。
variable might not have been initialized。public class Test {
int field; // 成員變量,默認 0
void method1() {
int local; // 局部變量,無默認值
if (local == field) // ❌ 編譯錯誤:local might not have been initialized
System.out.println("eq");
}
void method2() {
int local = 0; // ✅ 顯式初始化
if (local == field) // ✅ 合法
System.out.println("eq");
}
}
Java 只有值傳遞。對象引用作為參數時,傳遞的是引用的副本(地址值)。
void modify(StringBuffer a, StringBuffer b) {
a = a.append(b); // a 重新指向新對象(或同一對象),不影響實參引用
b = a; // b 也指向同一對象,僅改變形參引用
}
StringBuffer x = new StringBuffer("a");
StringBuffer y = new StringBuffer("b");
modify(x, y);
// 此處 x 仍指向原 "a" 對象(內容已變為 "ab"),y 仍指向 "b"
a.append(b) 修改了對象內部狀態,實參 x 可見。a = ... 修改的是形參引用變量本身,實參不受影響。final 字段 + 無 setter)優先,簡化併發。this 逃逸),導致對象未完全初始化就被其他線程訪問。