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

Java 參數傳遞機制真相:值傳遞、引用傳值與遠程調用邊界

     編輯:Java 相關知識

核心結論:Java 只有值傳遞

無論基本類型還是引用類型,**方法參數傳遞的都是「值的副本」**。

  • 基本類型:複製數值本身,方法內修改不影響外部。
  • 引用類型:複製引用地址(指向堆對象的指針),方法內可通過引用修改對象內容,但無法改變外部變量指向的對象(重新賦值參數變量僅改變局部副本)。

代碼驗證

public class ParamDemo {
    static class MyClass { int i; }
    
    public static void main(String[] args) {
        int primitive = 2;
        changePrimitive(primitive);
        System.out.println("primitive=" + primitive); // 2,未變
        
        MyClass obj = new MyClass();
        obj.i = 1;
        changeObject(obj);
        System.out.println("obj.i=" + obj.i);        // 3,內容被修改
        System.out.println("obj hash=" + System.identityHashCode(obj)); // 同一對象
    }
    
    static void changePrimitive(int p) { p = 3; } // 修改副本
    
    static void changeObject(MyClass p) {
        p.i = 3;          // 通過引用修改對象內容 ✓
        p = new MyClass(); // 修改局部引用副本,外部 obj 不受影響 ✗
    }
}

圖解內存模型

調用前:           調用 changeObject(obj) 時:
main棧幀           changeObject棧幀
┌─────────┐        ┌─────────┐
│ obj ──────────→  │ p  ──────────→  ┌─────────┐
└─────────┘        └─────────┘     │ MyClass │
                                   │ i = 1   │
堆內存                              └─────────┘
┌─────────┐
│ MyClass │ ←── obj, p 共同指向
│ i = 1   │
└─────────┘

執行 p = new MyClass() 後:
changeObject棧幀
┌─────────┐
│ p  ──────────→  ┌─────────┐
└─────────┘     │ MyClass │
                │ i = 0   │
堆內存          └─────────┘
┌─────────┐     ┌─────────┐
│ MyClass │     │ MyClass │ ←── p 指向新對象
│ i = 3   │     │ i = 0   │
└─────────┘     └─────────┘
                ↑
main棧幀 obj 仍指向舊對象(i=3)

常見誤區澄清

誤區真相
Java 對象是引用傳遞引用本身是值傳遞(傳引用的副本)
方法內 new 同類對象能影響外部只能修改共享對象內容,不能換掉外部引用指向
基本類型包裝類傳遞能修改值Integer 等不可變,拆箱/裝箱產生新對象,同引用類型規則

特殊場景

數組參數

數組是對象,引用傳值。方法內 arr[0]=99 影響外部;arr = new int[5] 不影響。

集合參數

list.add("x") 影響外部;list = new ArrayList() 不影響。若需替換整個集合,返回新集合或用 List<T>[] 數組包裝、AtomicReference、回調函數。

遠程調用(RMI、Dubbo、gRPC、HTTP)

完全隔離:參數經序列化→網絡傳輸→反序列化,得到全新對象圖。服務端修改參數對象絕不影響客戶端原對象。這是分布式系統「共享內存 vs 共享無」的本質區別。

本地接口(EJB Local、Spring 同進程 Bean)

同 JVM 內直接調用,遵循標準值傳遞規則,共享堆對象。

最佳實踐

  1. 方法參數優先用不可變類型(String、包裝類、Record、Value Object),消除副作用認知負擔。
  2. 需修改調用者狀態時:返回新對象(函數式風格)、或傳入可變容器(List、Map、StringBuilder)並明確文檔說明「輸出參數」。
  3. 避免「引用傳遞」幻覺導致的 Bug:代碼審查重點檢查參數重新賦值邏輯。
  4. 分布式介面設計:參數/返回值必須可序列化,無循環引用,版本兼容序列化策略。
理解「值傳遞」是 Java 程序員的分水嶺。搞清「傳的是引用的值,不是引用本身」,90% 的參數修改困惑迎刃而解。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved