public class Listaa {
private static List list = new ArrayList();
private static int i; // ← 關鍵:static 靜態字段!
public static void maain(int i) {
Listaa t = new Listaa();
t.setI(i);
list.add(t);
}
public static void main(String[] args) {
for (int i = 0; i < 3; i++) maain(i);
for (int i = 0; i < list.size(); i++) {
Listaa a = (Listaa) list.get(i);
System.out.println(a.getI()); // 輸出:2 2 2 (預期 0 1 2)
}
}
// getter/setter 省略
}
private static int i 導致:
Listaa 實例**共享同一個** i 字段(內存中只有一份)。maain(0)、maain(1)、maain(2) 時,每次 t.setI(i) 都在**覆蓋同一個靜態變量**。i = 2,列表中三個引用指向的對象雖不同,但其 i 字段指向同一記憶體地址,讀取時全為 2。Heap:
+------------------+
| Listaa@1 | i → |──┐
+------------------+ │
| Listaa@2 | i → |──┤ 同一地址
+------------------+ │
| Listaa@3 | i → |──┘
+------------------+
Static Area:
int i = 2 (最終值)
public class Listaa {
private List<Listaa> list = new ArrayList<>(); // 也建議改為實例字段
private int i; // ← 非 static,每個對象擁有獨立副本
public void maain(int i) {
Listaa t = new Listaa();
t.setI(i);
list.add(t);
}
public static void main(String[] args) {
Listaa app = new Listaa();
for (int i = 0; i < 3; i++) app.maain(i);
for (Listaa a : app.list) {
System.out.println(a.getI()); // 正確輸出:0 1 2
}
}
// getter/setter
}
| 錯誤模式 | 後果 | 修正 |
|---|---|---|
| 集合字段聲明 static | 所有實例共享同一列表,數據串聯 | 改為實例字段,或傳入外部列表 |
| 循環中重用同一對象引用 | List.add(obj) 多次添加同一引用 | 循環內 new Object() 創建新實例 |
| 匿名內部類捕獲循環變量 | 閉包引用同一變量,最終值一致 | 引入 final 局部變量副本 |
static 字段是類級別的單一存儲槽。將本應屬於對象狀態的數據誤標為 static,會導致所有實例共享同一值,這是 Java 新手最經典的「引用共享」Bug。記住:實例數據 → 實例字段;類級別常量/工具 → static final。