遇到下面一段代碼,結果是什麼:
public class StringbuilderAppend {
public static void test(StringBuilder x,StringBuilder y){
x.append(y);
y=x;
}
public static void main(String[] args) {
StringBuilder a=new StringBuilder("A");
StringBuilder b=new StringBuilder("B");
test(a,b);
System.out.println(a);
System.out.println(b);
}
}
發現和我想的不一樣,不是說java參數傳遞是值傳遞(傳的是棧空間的值,對於引用對象傳的就是地址了)嗎?爲什麼執行完程序,結果卻和自己想的不一樣呢?
原來還是對String、StringBuilder類型理解的不夠透徹;下面就來分析一下:
StringBuilder的append方法,append方法的操作是直接在原來的數據上進行字符串拼接;append操作是在原有對象的基礎上進行的;
執行過程如下:
代碼中a、b爲實參,調用函數,將a的地址 、b的地址傳遞給形參x、y,會發現a、x地址相同,指向同一個值;b、y地址相同,指向同一個值;如圖:
在函數中,執行
x.append(y);
y=x;
由於append方法是在原有對象的數據上進行操作的,所以執行完x.append(y);這一句代碼後,x指向的數據就變化了,但x的地址沒有變,又由於a和x的地址一樣,指向同一個對象,雖然a和x的指向都沒變,但是他們指向的數據發生了改變;所以a地址指向的數據也變化了;
y=x;這使形參y指向x的對象,只改變了形參y的指向,並沒有改變實參b的指向,所以b的值不變;如圖:
再來說一下String,先通過一段代碼來引入:
public class StringTest {
public static void test(String x,String y){
x=x+"A";
y=y+"A";
System.out.println("x:"+x);
System.out.println("y:"+y);
}
public static void main(String[] args) {
String a="C";
String c="D";
test(a,c);
System.out.println(a);
System.out.println(c);
}
}
結果爲:
首先,我們要明確一點:String類型是不可變的,是指其地址不可變,但其引用指向的內容是可變的;
String類由final修飾:
public final class String implements Serializable, Comparable<String>, CharSequence
’
且String類繼承了Comparable接口,自身帶有比較的功能;
上述代碼的執行如下:
代碼中a、c爲實參,調用函數,將a的地址 、c的地址傳遞給形參x、y,會發現a、x地址相同,指向同一個值;c、y地址相同,指向同一個值;
在函數中,對x、y進行操作,
x=x+"A";
y=y+"A";
因爲String類型是不可變的(引用不可變,引用指向的內容可變),它是取出x的值與‘A’相拼接,形成一個新的String對象,使 x重新 指向該新對象;所以 x 的地址改變了,指向的值改變了,但a的地址並沒有變,且a指向的內容也沒有變;同理,對y和c也是一樣,所以會出現這樣的結果;