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

Java 參數傳遞機制深度解析:值傳遞vs引用傳遞,基本類型、String、物件參數行為完整驗證

     編輯:Java 相關知識

結論先行

Java 唯有值傳遞(Call by Value)。基本類型傳值的副本;參考類型傳引用的副本(即記憶體地址副本)。

四大場景實證

1. 基本類型:值副本,原值不變

void change(int i) { i = 11; }
int x = 10; change(x); // x 仍為 10

2. String:不可變,重新指向新物件

void change(String s) { s = "ppp"; }
String str = "abc"; change(str); // str 仍為 "abc"

s = "ppp" 等同 s = new String("ppp"),只是讓區域變數指向新物件,不影響呼叫端引用。

3. 可變物件:引用副本指向同一物件,可修改內部狀態

void change(StringBuffer sb) { sb.append("ppp"); }
StringBuffer buf = new StringBuffer("abc");
change(buf); // buf 變為 "abcppp"

引用副本指向同一堆積物件,透過副本呼叫方法修改內容,原引用可見變化。

4. 參考類型重新指向:區域變數指向新物件,原引用不變

void change(StringBuffer sb) {
    sb = new StringBuffer(); // 區域變數指向新物件
    sb.append("ppp");
}
StringBuffer buf = new StringBuffer("abc");
change(buf); // buf 仍為 "abc"

關鍵:參數本身是區域變數,重新賦值只改變區域變數指向,不影響呼叫端的引用變數。

5. 集合/List 同理

void change(List list) { list.add("ppp"); }
List l = new ArrayList<>(); l.add("abcd");
change(l); // l 變為 [abcd, ppp]

void change2(List list) {
    list = new ArrayList<>(); // 重新指向
    list.add("ppp");
}
change2(l); // l 不變

記憶體圖解

呼叫端:  buf ──────┐
              │      ▼
參數:      sb ──────┘  同一物件 (可修改內容)

呼叫端:  buf ──────┐
              │
參數:      sb ──────┘  (重新指向) ───▶ 新物件

實務建議

  • 若需讓呼叫端看到新物件,回傳新物件或使用包裝類別(如 AtomicReference、單元素陣列)。
  • 不可變類別(String、Integer、BigDecimal 等)天然安全,無副作用。
  • API 設計時,明確文件化「是否修改傳入物件內部狀態」與「是否回傳新物件」。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved