public class Test { public static void test(String str) { str = "world"; } public static void main(String[] args) { String str1 = new String("hello"); test(str1); System.out.println(str1); } }
public class Test { public static void test(StringBuffer str) { str.append(" world"); } public static void main(String[] args) { StringBuffer str1 = new StringBuffer("hello"); test(str1); System.out.println(str1); } }
理解這兩個例子需要分清實參和形參的區別,引用和對象的區別
第一個例子的內部執行過程:
1.引用str1指向新對象new String("hello")。
2.test( )剛剛開始調用時,形參(parameter)str復制了實參(argument)str1的值,這個值也就是對象new String("hello")的地址,所以這時候引用str和引用str1指向同一個對象"hello"。
3.進入到test( )方法內部,“world”這個對象被分配給形參str,而這個操作對實參str1並沒有影響,所以這時候,引用str指向"world",而引用str1仍然指向原來的對象"hello"。
4.test( )方法結束后,形參str從棧內存中消失,他指向的對象"world"由於沒有其他引用指向它,也可以被gc回收了。
4.打印引用str1指向的對象,即"hello"。
第二個例子的內部執行過程:
1.引用str1指向新對象new StringBuffer("hello")。
2.test( )剛剛開始調用時,形參(parameter)str復制了實參(argument)str1的值,這個值也就是對象new StringBuffer("hello")的地址,所以這時候引用str和引用str1指向同一個對象"hello"。
3.進入到test( )方法內部,形參str調用append方法," world"附加到了引用str所指向的對象"hello"后面,由於形參str和實參str1指向的是同一個對象,所以這個操作同時也改變了引用str1指向的對象,因此這時候,引用str和str1指向同一個對象"hello world"。
4.test( )方法結束后,形參str從棧內存中消失,他指向的對象"hello world"由於仍然有引用str1指向它,不滿足被回收的條件。
5.打印引用str1指向的對象,即"hello world"。
理解這個例子后,回到原題,到底是傳值還是傳引用,一直是個有爭議的問題,這個例子中,可以理解為值傳遞,這個值,就是引用所指向的對象的地址。