Java 方法參數傳遞唯一機制是值傳遞。對於基本類型傳遞值的副本;對於引用類型傳遞引用的副本(即內存地址副本)。這一點與 C++ 的引用傳遞、C 的指針傳遞本質不同。
public class People {
private String name;
private int age;
// 構造器、getter/setter、toString 省略
}
public class ParamPassTest {
/**
* 交換引用:僅影響方法內部局部變量
*/
public static void swapRef(People a, People b) {
People temp = a;
a = b;
b = temp;
// 此處 a、b 已交換,但外部實參引用不變
}
/**
* 修改對象內容:通過引用副本訪問同一堆對象
*/
public static void modifyObject(People p) {
p.setName("Changed");
p.setAge(99);
}
public static void main(String[] args) {
People p1 = new People("Alice", 20);
People p2 = new People("Bob", 25);
System.out.println("調用前: p1=" + p1 + ", p2=" + p2);
// 輸出: p1=Alice/20, p2=Bob/25
swapRef(p1, p2);
System.out.println("swapRef後: p1=" + p1 + ", p2=" + p2);
// 輸出: p1=Alice/20, p2=Bob/25 —— 外部引用未變
modifyObject(p1);
System.out.println("modifyObject後: p1=" + p1);
// 輸出: p1=Changed/99 —— 對象內容被修改
}
}
棧幀 main() 堆內存 ┌─────────────────┐ ┌──────────────┐ │ p1 ─────────────┼─────►│ People@1001 │ │ p2 ─────────────┼─────►│ People@1002 │ └─────────────────┘ └──────────────┘ 棧幀 swapRef() 堆內存(同一對象) ┌─────────────────┐ ┌──────────────┐ │ a ──────────────┼─────►│ People@1001 │ │ b ──────────────┼─────►│ People@1002 │ └─────────────────┘ └──────────────┘ a、b 為 p1、p2 的引用副本,指向同一對象 交換 a、b 僅改變局部引用指向,不影響 p1、p2
| 誤區 | 事實 |
|---|---|
| Java 對象傳遞是引用傳遞 | 傳遞的是引用的副本,屬於值傳遞的一種 |
| 方法內修改對象屬性說明是引用傳遞 | 通過引用副本可訪問同一對象,屬於「通過引用訪問」,非「引用傳遞」 |
| swap 能交換對象 | 無法交換外部引用,只能交換方法內部局部引用變量 |
String、包裝類、LocalDate 等天然線程安全,無副作用風險Collections.unmodifiableList 或傳遞副本 new ArrayList<>(list)