Java中只有按值传递,没有按引用传递!
今天,我在一本面試書上看到了關(guān)于java的一個(gè)參數(shù)傳遞的問(wèn)題:
原文地址:http://guhanjie.iteye.com/blog/1683637?
寫道 java中對(duì)象作為參數(shù)傳遞給一個(gè)方法,到底是值傳遞,還是引用傳遞??我毫無(wú)疑問(wèn)的回答:“引用傳遞!”,并且還覺(jué)得自己對(duì)java的這一特性很是熟悉!
結(jié)果發(fā)現(xiàn),我錯(cuò)了!
答案是:
值傳遞!Java中只有按值傳遞,沒(méi)有按引用傳遞!
?
回家后我就迫不及待地查詢了這個(gè)問(wèn)題,覺(jué)得自己對(duì)java這么基礎(chǔ)的問(wèn)題都搞錯(cuò)實(shí)在太丟人!
?
綜合網(wǎng)上的描述,我大概了解了是怎么回事,現(xiàn)在整理如下,如有不對(duì)之處望大神提出!
?
先來(lái)看一個(gè)作為程序員都熟悉的值傳遞的例子:
?
Java代碼???
答案顯而易見,調(diào)用函數(shù)changeValue()前后num的值都沒(méi)有改變。
?
由此做一個(gè)引子,我用圖表描繪一個(gè)值傳遞的過(guò)程:
?
num作為參數(shù)傳遞給changeValue()方法時(shí),是將內(nèi)存空間中num所指向的那個(gè)存儲(chǔ)單元中存放的值,即"5",傳送給了changeValue()方法中的x變量,而這個(gè)x變量也在內(nèi)存空間中分配了一個(gè)存儲(chǔ)單元,這個(gè)時(shí)候,就把num的值5傳送給了這個(gè)存儲(chǔ)單元中。此后,在changeValue()方法中對(duì)x的一切操作都是針對(duì)x所指向的這個(gè)存儲(chǔ)單元,與num所指向的那個(gè)存儲(chǔ)單元沒(méi)有關(guān)系了!
自然,在函數(shù)調(diào)用之后,num所指向的存儲(chǔ)單元的值還是沒(méi)有發(fā)生變化,這就是所謂的“值傳遞”!值傳遞的精髓是:傳遞的是存儲(chǔ)單元中的內(nèi)容,而非地址或者引用!
?
接下來(lái),就來(lái)看java中的對(duì)象參數(shù)是怎么傳遞的:
同樣,先給出一段代碼:
Java代碼???
?答案應(yīng)該大家都心知肚明:
第一次顯示:“Jack”
第二次顯示:“Rose”
?
方法用了一個(gè)對(duì)象參數(shù),該對(duì)象內(nèi)部的內(nèi)容就可以改變,我之前一直認(rèn)為應(yīng)該是該對(duì)象復(fù)制了一個(gè)引用副本給調(diào)用函數(shù)的參數(shù),使得該方法可以對(duì)這個(gè)對(duì)象進(jìn)行操作,其實(shí)是錯(cuò)了!
http://www.cnblogs.com/clara/archive/2011/09/17/2179493.html 寫道 Java 編程語(yǔ)言只有值傳遞參數(shù)。當(dāng)一個(gè)對(duì)象實(shí)例作為一個(gè)參數(shù)被傳遞到方法中時(shí),參數(shù)的值就是該對(duì)象的引用一個(gè)副本。指向同一個(gè)對(duì)象,對(duì)象的內(nèi)容可以在被調(diào)用的方法中改變,但對(duì)象的引用(不是引用的副本)是永遠(yuǎn)不會(huì)改變的。??
為什么這里是“值傳遞”,而不是“引用傳遞”?
我還是用圖表描繪比較能解釋清楚:
?
?
主函數(shù)中new 了一個(gè)對(duì)象Person,實(shí)際分配了兩個(gè)對(duì)象:新創(chuàng)建的Person類的實(shí)體對(duì)象,和指向該對(duì)象的引用變量person。
【注意:在java中,新創(chuàng)建的實(shí)體對(duì)象在堆內(nèi)存中開辟空間,而引用變量在棧內(nèi)存中開辟空間】
正如如上圖所示,左側(cè)是堆空間,用來(lái)分配內(nèi)存給新創(chuàng)建的實(shí)體對(duì)象,紅色框是新建的Person類的實(shí)體對(duì)象,000012是該實(shí)體對(duì)象的起始地址;而右側(cè)是棧空間,用來(lái)給引用變量和一些臨時(shí)變量分配內(nèi)存,新實(shí)體對(duì)象的引用person就在其中,可以看到它的存儲(chǔ)單元的內(nèi)容是000012,記錄的正是新建Person類實(shí)體對(duì)象的起始地址,也就是說(shuō)它指向該實(shí)體對(duì)象。
這時(shí)候,好戲上臺(tái)了:
調(diào)用了changeName()方法,person作為對(duì)象參數(shù)傳入該方法,但是大家特別注意,它傳入的是什么!!!person引用變量將自己的存儲(chǔ)單元的內(nèi)容傳給了changeName()方法的p變量!也就是將實(shí)體對(duì)象的地址傳給了p變量,從此,在changeName()方法中對(duì)p的一切操作都是針對(duì)p所指向的這個(gè)存儲(chǔ)單元,與person引用變量所指向的那個(gè)存儲(chǔ)單元再?zèng)]有關(guān)系了!
回顧一下上面的一個(gè)值傳遞的例子,值傳遞,就是將存儲(chǔ)單元中的內(nèi)容傳給調(diào)用函數(shù)中的那個(gè)參數(shù),這里是不是異曲同工,是所謂“值傳遞”,而非“引用傳遞”!!!
?
那為什么對(duì)象內(nèi)部能夠發(fā)生變化呢?
那是因?yàn)?#xff1a;p所指向的那個(gè)存儲(chǔ)單元中的內(nèi)容是實(shí)體對(duì)象的地址,使得p也指向了該實(shí)體對(duì)象,所以才能改變對(duì)象內(nèi)部的屬性!
這也是我們大多數(shù)人會(huì)誤以為是“引用傳遞”的終極原因!!!
總結(jié)
以上是生活随笔為你收集整理的Java中只有按值传递,没有按引用传递!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 设计模式:回调模式
- 下一篇: 内存可见性和原子性:Synchroniz