一道筆試題來理順Java中的值傳遞和引用傳遞

前段時間參加了一場面試,其中有一道引用傳遞的題,由於當時並無考慮清楚因此作錯了。 
如今來複盤一下,題目以下:
html

private static void change(StringBuffer str11, StringBuffer str12) {

str12 = str11;
str11 = new StringBuffer("new world");
str12.append("new world");
}

public static void main(String[] args) {
StringBuffer str1 = new StringBuffer("good ");
StringBuffer str2 = new StringBuffer("bad ");
change(str1, str2);
System.out.println(str1.toString());
System.out.println(str2.toString());
}
 
就是這麼一個很簡單的題目,你們應該知道答案吧? 答案是:

good new world 
badweb

下面就來複盤一下爲什麼是這兩個答案,下面會作詳細的圖文分析。 
要搞明白這個問題,那麼就須要明白Java中的值傳遞和引用傳遞了。
面試

Java對象參數傳遞雖然傳遞的是地址(引用),但仍然是值調用。是時候須要給引用調用和值調用一個準確的定義了。編程

  • 值調用(call by value): 在參數傳遞過程當中,形參和實參佔用了兩個徹底不一樣的內存空間。形參所存儲的內容是實參存儲內容的一份拷貝。實際上,Java對象的傳遞就符合這個定義,只不過形參和實參所儲存的內容並非常規意義上的變量值,而是變量的地址。咳,回過頭想一想:變量的地址不也是一種值嗎!app

  • 引用調用(call by reference) : 在參數傳遞的過程當中,形參和實參徹底是同一塊內存空間,二者不分彼此。 實際上,形參名和實參名只是編程中的不一樣符號,在程序運行過程當中,內存中存儲的空間纔是最重要的。不一樣的變量名並不能說明佔用的內存存儲空間不一樣。ide

那麼接下來就畫圖分析文章開頭拋出的問題: 
這裏再把代碼貼一遍,你們能夠對比着代碼和圖一塊兒看。
函數

private static void change(StringBuffer str11, StringBuffer str12) {

str12 = str11;//2
str11 = new StringBuffer("new world");//3
str12.append("new world");//4
}//5

public static void main(String[] args) {
StringBuffer str1 = new StringBuffer("good ");
StringBuffer str2 = new StringBuffer("bad ");
change(str1, str2);//1
System.out.println(str1.toString());
System.out.println(str2.toString());
}
 
  • 執行到第一步的圖: 
    spa

     

  • 執行到第二步的圖,這裏chage方法中的形參str11,str22是實參str1,str2的地址拷貝。 
    orm

     

  • 這裏str11和str22是實參str1,str2的地址拷貝,接着執行第三步的圖: 
    htm

     

  • 上圖中str12地址指向了「good」,接着看第四步圖: 

     

  • 上圖中str11的地址指向了堆中新的對象"new world",接着看第五步的圖: 

     

這裏圖算是畫完了,確實不太擅長畫圖,你們就先勉強看吧。 
這裏有一個很重要的點就是StringBuffer是可變的,具體解釋你們能夠搜索下。

由於這裏str12.append("new world")直接修改了good的值。因此main函數中打印的會是:good new world。

到這裏就算講完了,一個很簡單的例子,這裏算是對以前一道筆試題的覆盤,有不對的地方歡迎你們指正。

相關文章
相關標籤/搜索