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

Java 參數傳遞機制深度解析:為什麼無法直接交換兩個變量值?

     編輯:Java 綜合教學

核心結論:Java 只有值傳遞

Java 方法參數傳遞唯一採用按值傳遞。方法接收的是參數值的拷貝,無法修改調用者變量的內容——這對基本類型和引用類型均適用。

三類參數傳遞方式對比

傳遞方式傳遞內容能否修改原變量典型語言
按值傳遞變量值的拷貝不能Java、C、Python(不可變對象)
按引用傳遞變量的地址/別名能C++、C#(ref/out)
按指針傳遞指針的拷貝可修改指向內容,不可修改指針本身C、C++

Java 兩類參數類型行為差異

基本數據類型

方法接收值的拷貝,任何修改僅影響副本,原變量不變。

引用類型(對象)

方法接收引用的拷貝(即對象地址的拷貝)。兩個引用指向同一堆對象,因此:

  • ✅ 可修改對象內部狀態(調用 setter、修改字段)
  • ❌ 無法讓原引用指向新對象(重新賦值僅改變副本引用)

代碼驗證:修改對象狀態 vs 交換引用

場景一:修改對象狀態(成功)

public class MyClass {
    private Object num;
    public MyClass(Object num) { this.num = num; }
    public Object getNum() { return num; }
    public void setNum(Object num) { this.num = num; }
}

public static void change(MyClass myClass) {
    myClass.setNum(100); // 修改對象內部狀態
}

public static void main(String[] args) {
    MyClass a = new MyClass(10);
    System.out.println("調用前: " + a.getNum()); // 10
    change(a);
    System.out.println("調用後: " + a.getNum()); // 100 ✅
}

場景二:嘗試交換引用(失敗)

public static void swap(MyClass a, MyClass b) {
    MyClass tmp = a;
    a = b;
    b = tmp; // 僅交換了局部引用副本
}

public static void main(String[] args) {
    MyClass a = new MyClass(10);
    MyClass b = new MyClass(100);
    System.out.println("交換前 a: " + a.getNum()); // 10
    System.out.println("交換前 b: " + b.getNum()); // 100
    swap(a, b);
    System.out.println("交換後 a: " + a.getNum()); // 10 ❌ 未變
    System.out.println("交換後 b: " + b.getNum()); // 100 ❌ 未變
}

內存模型圖解

調用 change() 時:

main棧幀: a ──────► 堆對象 [num=10]
                     ▲
change棧幀: myClass ┘  (引用拷貝,指向同一對象)
修改 myClass.num → 堆對象 [num=100] → main 中 a 看到變化

調用 swap() 時:

main棧幀: a ──────► 堆對象A [num=10]
              b ──────► 堆對象B [num=100]

swap棧幀: a' ──────► 堆對象A (a的拷貝)
          b' ──────► 堆對象B (b的拷貝)
交換 a'、b' 僅影響 swap 棧幀,main 棧幀 a、b 完全不受影響

正確交換對象內容的方法

既然無法交換引用,就交換對象內部狀態:

public static void swap(MyClass a, MyClass b) {
    Object tmp = a.getNum();
    a.setNum(b.getNum());
    b.setNum(tmp); // 交換內部字段值
}

// 驗證
System.out.println("交換後 a: " + a.getNum()); // 100 ✅
System.out.println("交換後 b: " + b.getNum()); // 10 ✅

總結:Java 參數傳遞三鐵律

  1. 方法不能修改基本類型參數的值
  2. 方法可以修改對象參數的內部狀態
  3. 方法不能讓對象參數引用指向新對象

參考文獻

《Java 核心技術 卷Ⅰ》—— Cay S. Horstmann

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