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

Java 交換對象失敗:值傳遞機制下的引用拷貝陷阱

     編輯:程式設計疑難解答

問題代碼

public static void swap(Employee x, Employee y) {
    Employee temp = x;
    x = y;
    y = temp;
    System.out.println("x:" + x.getName()); // 輸出 b
    System.out.println("y:" + y.getName()); // 輸出 a
}

public static void main(String[] args) {
    Employee a = new Employee("a", ...);
    Employee b = new Employee("b", ...);
    swap(a, b);
    System.out.println("a:" + a.getName()); // 輸出 a (未變!)
    System.out.println("b:" + b.getName()); // 輸出 b (未變!)
}

核心原因:Java 是值傳遞

  • 方法參數傳遞的是引用的副本 (reference copy)
  • swap 方法中交換的是局部變量 x、y 指向的引用
  • 原始引用 a、b 在主方法棧幀中完全不受影響

內存圖解

調用前:
main棧幀: a ──────→ Employee@100 ("a")
          b ──────→ Employee@200 ("b")

swap棧幀: x ──────→ Employee@100 ("a")  (拷貝 a 的引用值)
          y ──────→ Employee@200 ("b")  (拷貝 b 的引用值)

swap 內部交換后:
          x ──────→ Employee@200 ("b")
          y ──────→ Employee@100 ("a")

swap 返回,棧幀銷毀,x/y 消失
main棧幀 a/b 引用未變

正確交換方案

方案一:交換對象內部屬性(推薦)

public static void swapContent(Employee x, Employee y) {
    String tempName = x.getName();
    x.setName(y.getName());
    y.setName(tempName);
    // 同理交換其他屬性...
}
// 原始對象內容被修改,引用不變

方案二:包裝類 / 數組 / 容器持有引用

// 使用數組包裝
Employee[] wrapper = {a, b};
swapArray(wrapper);
// wrapper[0] 現在指向 b, wrapper[1] 指向 a

public static void swapArray(Employee[] arr) {
    Employee temp = arr[0];
    arr[0] = arr[1];
    arr[1] = temp;
}

方案三:返回新對象/引用 (函數式風格)

public static Employee[] swapReturn(Employee a, Employee b) {
    return new Employee[]{b, a};
}
// 使用: Employee[] swapped = swapReturn(a, b); a = swapped[0]; b = swapped[1];

對比:C++ 引用傳遞可直接交換

void swapCpp(Employee& x, Employee& y) { // 引用參數
    Employee temp = x;
    x = y;
    y = temp;
}
// 直接修改原始對象引用綁定

總結

Java 無引用傳遞,只有值傳遞(基本類型傳值,引用類型傳引用值)。方法內無法修改調用者棧幀中的引用變量本身,只能通過引用修改對象內部狀態。理解這一點是掌握 Java 參數傳遞的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved