public class Example {
String str = new String("good");
char[] ch = {'a', 'b', 'c'};
public static void main(String args[]) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public void change(String str, char ch[]) {
str = "test ok";
ch[0] = 'g';
}
}
執行結果: good and gbc
疑問:為什麼 str 沒變,而 ch 卻改變了?
Java 中方法參數傳遞永遠是值傳遞。但「值」的含義因類型而異:
Example ex = new Example(); 後Example 對象,包含兩個實例字段:
str → 指向字符串對象 "good"(常量池/堆)ch → 指向字符數組對象 {'a','b','c'}ex 變量持有該對象引用。ex.change(ex.str, ex.ch) 進入方法str 複製了實參 ex.str 的引用值(指向 "good")。ch 複製了實參 ex.ch 的引用值(指向同一數組對象)。str = "test ok";"test ok"。str 的引用指向新對象。ex.str 仍指向原 "good",完全不受影響。ch[0] = 'g';ch 仍指向原數組對象。'a' 改為 'g'。ex.ch 指向同一數組,故外部可見變化。| 操作 | 形參引用 | 實參引用 | 對象內容 | 外部可見性 |
|---|---|---|---|---|
str = "test ok" | 指向新對象 | 不變 | 舊對象不變 | 不可見 |
ch[0] = 'g' | 不變 | 不變 | 共同指向的數組被修改 | 可見 |
StringBuilder 或返回新字符串供調用者重新賦值。list = new ArrayList())則不會。這道題考察的核心是「引用傳值」而非「引用傳遞」。理解記憶體模型(棧、堆、常量池)與引用副本機制,是攻克 Java 參數傳遞難題的鑰匙。