Java 只有值傳遞。String 作為不可變物件,在方法中「修改」實際是建立新物件,原參數仍指向舊物件,外部引用不受影響。
public void test() {
String s = "original";
change(s);
System.out.println(s); // 輸出: original
}
public void change(String s) {
s = s + " changed"; // 建立新 String 物件
System.out.println(s); // 輸出: original changed
}
String s = new String("original");
changeNew(s); // 同樣輸出 original
證實:賦值方式 (字面值 vs new) 不影響參數傳遞行為。
String s = new String("original");
changeByMethod(s); // 同樣輸出 original
public void changeByMethod(String s) {
s = s.concat(" changed"); // 同樣建立新物件
}
證實:修改手段 (運算子 vs 方法) 不影響結果。
public final class String implements Serializable, Comparable {
private final char[] value; // JDK 8 及之前
// private final byte[] value; // JDK 9+ Compact Strings
private final int hash; // 快取 hashCode
// ...
}
final 欄位:初始化後不可變更引用concat、replace、substring、+) 皆回傳新 String 實例String 本質上是 char[]/byte[] 的不可變包裝類,行為與 Integer、Long 完全一致:
Integer i = 10;
change(i); // 外部 i 仍為 10
void change(Integer i) {
i = i + 1; // 自動拆箱、運算、裝箱 → 新 Integer 物件
}
呼叫前:
main 棧幀: s ──────► 堆: "original" (String 物件)
呼叫 change(s) 後:
main 棧幀: s ──────► 堆: "original" (未變)
change 棧幀: param ─► 堆: "original changed" (新物件)
change 返回,棧幀銷毀:
main 棧幀: s ──────► 堆: "original" (依然指向舊物件)
hash 欄位一次計算永久有效,Map Key 高效// 高效字串拼接
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) sb.append(i);
String result = sb.toString();
// 多執行緒環境
StringBuffer sbf = new StringBuffer(); // 同步安全
| 類型 | 傳遞機制 | 方法內修改影響外部 | 典型代表 |
|---|---|---|---|
| 基本類型 | 值傳遞 (複製位元) | 否 | int, double, boolean |
| 物件引用 | 值傳遞 (複製引用) | 是 (修改物件內部狀態) | StringBuilder, List, 自訂類 |
| 不可變物件 | 值傳遞 (複製引用) | 否 (無法修改內部狀態,賦值建立新物件) | String, Integer, LocalDate |