Java 唯有值傳遞(Call by Value)。基本類型傳值的副本;參考類型傳引用的副本(即記憶體地址副本)。
void change(int i) { i = 11; }
int x = 10; change(x); // x 仍為 10
void change(String s) { s = "ppp"; }
String str = "abc"; change(str); // str 仍為 "abc"
s = "ppp" 等同 s = new String("ppp"),只是讓區域變數指向新物件,不影響呼叫端引用。
void change(StringBuffer sb) { sb.append("ppp"); }
StringBuffer buf = new StringBuffer("abc");
change(buf); // buf 變為 "abcppp"
引用副本指向同一堆積物件,透過副本呼叫方法修改內容,原引用可見變化。
void change(StringBuffer sb) {
sb = new StringBuffer(); // 區域變數指向新物件
sb.append("ppp");
}
StringBuffer buf = new StringBuffer("abc");
change(buf); // buf 仍為 "abc"
關鍵:參數本身是區域變數,重新賦值只改變區域變數指向,不影響呼叫端的引用變數。
void change(Listlist) { 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、單元素陣列)。