首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java static 變數傳遞陷阱:方法參數遮蔽靜態欄位導致 null

     編輯:程式設計綜合問答

問題代碼

public class StaticTest {
    private static List listA;
    private static List listB;
    static {
        listA = new ArrayList<>();
        listA.add("aaa");
        setB(listB); // 傳入 null
    }
    private static void setB(List listB) { // 參數名同欄位名
        if (listB == null) {
            listB = new ArrayList<>(); // 僅修改區域參數
            listB.add("bbb");
        }
    }
    public static void main(String[] args) {
        System.out.println(listB == null); // true
    }
}

根本原因

方法參數 listB **遮蔽** 了靜態欄位 listB。方法內 listB = new ArrayList...() 僅改變**區域參數引用**,靜態欄位仍為 null。

修正方式

1. 參數改名 (最簡單)

private static void setB(List target) {
    if (target == null) {
        target = new ArrayList<>();
        target.add("bbb");
    }
    listB = target; // 明確賦值給靜態欄位
}

2. 使用 `this` (非靜態方法) 或類名限定

private static void setB(List listB) {
    if (listB == null) {
        StaticTest.listB = new ArrayList<>(); // 類名.欄位
        StaticTest.listB.add("bbb");
    }
}

3. 直接回傳新列表 (函數式風格)

private static List initB() {
    List b = new ArrayList<>();
    b.add("bbb");
    return b;
}
static {
    listA = new ArrayList<>();
    listA.add("aaa");
    listB = initB();
}

核心觀念

  • Java **傳值呼叫**:傳遞的是參考的**副本**。
  • 參數重新指向新物件,**不影響**呼叫端原參考。
  • 靜態初始化區塊執行順序:依宣告順序,`listB` 尚未初始化即傳入 `setB`,故為 null。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved