String作為引用類型,為什么在主方法內調用子方法,子方法修改不了String的值
有趣的小例子
public class StringTest {
public static void main(String[] args) {
String str = new String("0");
System.out.println("+主方法調用子方法前 str = :" + str);
resetString(str);
//該處直接上,是不是應該輸出 change
System.out.println("+主方法調用子方法后 str = :" + str);
}
private static void resetString(String str) {
System.out.println(" -子方法中改變前 str = :" + str);
str = "change";
System.out.println(" -子方法中改變后 str = :" + str);
}
}
真實的輸出結果
+主方法調用子方法前 str = :0
-子方法中改變前 str = :0
-子方法中改變后 str = :change
+主方法調用子方法后 str = :0
子方法沒有起到重置str的作用
因為 String 為 final 修飾的類,所以創(chuàng)建的對象不能改變;str引用變量重新賦值,其實是在堆中是重新創(chuàng)建了一個實例對象,子方法中str引用變量指向了新的實例對象;
public class StringTest {
public static void main(String[] args) {
//1 主方法棧幀 中創(chuàng)建 str 引用變量;堆中創(chuàng)建 Stirng 為 0 的對象
String str = new String("0");
System.out.println("+主方法調用子方法前 str = :" + str);
//2 調用子方法
resetString(str);
//由 1 2 執(zhí)行步驟,可以看出 主方法棧幀中的 str引用對象指向的 0 對象沒有發(fā)生改變
System.out.println("+主方法調用子方法后 str = :" + str);
}
//2.1 主方法棧幀中 壓人 子方法棧幀
private static void resetString(String str) {
System.out.println(" -子方法中改變前 str = :" + str);
//2.2 堆中創(chuàng)建 change 對象;子方法棧幀中 str引用變量 執(zhí)行堆中新創(chuàng)建的 change對象
str = "change";
System.out.println(" -子方法中改變后 str = :" + str);
}
}
圖示如下:

棧幀和堆.png