今天,我在一本面試書上看到了關於java的一個參數傳遞的問題:html
我毫無疑問的回答:「引用傳遞!」,而且還以爲本身對java的這一特性非常熟悉!java
結果發現,我錯了!程序員
答案是:面試
值傳遞!Java中只有按值傳遞,沒有按引用傳遞!編程
回家後我就火燒眉毛地查詢了這個問題,以爲本身對java這麼基礎的問題都搞錯實在太丟人!編程語言
綜合網上的描述,我大概瞭解了是怎麼回事,如今整理以下,若有不對之處望大神提出!函數
先來看一個做爲程序員都熟悉的值傳遞的例子:spa
答案顯而易見,調用函數changeValue()先後num的值都沒有改變。htm
由此作一個引子,我用圖表描繪一個值傳遞的過程:對象
num做爲參數傳遞給changeValue()方法時,是將內存空間中num所指向的那個存儲單元中存放的值,即"5", 傳送給了changeValue()方法中的x變量,而這個x變量也在內存空間中分配了一個存儲單元,這個時候,就把num的值5傳送給了這個存儲單元 中。此後,在changeValue()方法中對x的一切操做都是針對x所指向的這個存儲單元,與num所指向的那個存儲單元沒有關係了!
天然,在函數調用以後,num所指向的存儲單元的值仍是沒有發生變化,這就是所謂的「值傳遞」!值傳遞的精髓是:傳遞的是存儲單元中的內容,而非地址或者引用!
接下來,就來看java中的對象參數是怎麼傳遞的:
一樣,先給出一段代碼:
答案應該你們都心知肚明:
第一次顯示:「Jack」
第二次顯示:「Rose」
方法用了一個對象參數,該對象內部的內容就能夠改變,我以前一直認爲應該是該對象複製了一個引用副本給調用函數的參數,使得該方法能夠對這個對象進行操做,實際上是錯了!
爲何這裏是「值傳遞」,而不是「引用傳遞」?
我仍是用圖表描繪比較能解釋清楚:
主函數中new 了一個對象Person,實際分配了兩個對象:新建立的Person類的實體對象,和指向該對象的引用變量person。
【注意:在java中,新建立的實體對象在堆內存中開闢空間,而引用變量在棧內存中開闢空間】
正如如上圖所示,左側是堆空間,用來分配內存給新建立的實體對象,紅色框是新建的 Person類的實體對象,000012是該實體對象的起始地址;而右側是棧空間,用來給引用變量和一些臨時變量分配內存,新實體對象的引用person 就在其中,能夠看到它的存儲單元的內容是000012,記錄的正是新建Person類實體對象的起始地址,也就是說它指向該實體對象。
這時候,好戲上臺了:
調用了changeName()方法,person做爲對象參數傳入該方法,可是大 家特別注意,它傳入的是什麼!!!person引用變量將本身的存儲單元的內容傳給了changeName()方法的p變量!也就是將實體對象的地址傳給 了p變量,今後,在changeName()方法中對p的一切操做都是針對p所指向的這個存儲單元,與person引用變量所指向的那個存儲單元再沒有關 繫了!
回顧一下上面的一個值傳遞的例子,值傳遞,就是將存儲單元中的內容傳給調用函數中的那個參數,這裏是否是殊途同歸,是所謂「值傳遞」,而非「引用傳遞」!!!
那爲何對象內部可以發生變化呢?
那是由於:p所指向的那個存儲單元中的內容是實體對象的地址,使得p也指向了該實體對象,因此才能改變對象內部的屬性!
這也是咱們大多數人會誤覺得是「引用傳遞」的終極緣由!!!