可能很多人都知道java中參數(shù)有形參和實參之分,卻不知道區(qū)別到底是什么;知道Java中內(nèi)存分為棧、堆、方法區(qū)等5片內(nèi)存,不知道每片內(nèi)存中保存的都是什么;關(guān)于參數(shù)的傳遞到底是值傳遞還是引用傳遞傻傻分不清楚。本文將為你逐一揭秘! 一、形參和實參:
test方法中的參數(shù)name就是形參,只有在test方法在被調(diào)用這個name的生命周期才開始,才會分配內(nèi)存空間,當(dāng)test方法調(diào)用完后,這個name也就不復(fù)存在。
這個String name = "劉亦菲"中這個name,在test方法被調(diào)用之前就就已被創(chuàng)建并且初始化,在調(diào)用test方法時,它就被當(dāng)作實際參數(shù)傳入,這就是實參。 二、Java中的內(nèi)存:Java中內(nèi)存分為5片,分別是棧、堆、方法區(qū)、程序計數(shù)器、本地方法棧。 1、棧:又稱虛擬機棧。特點是先進(jìn)后出。棧的線程是私有的,也就是線程之間的棧是隔離的。棧中有若干棧幀,每個棧幀對應(yīng)一個方法。也就是說,當(dāng)程序開始執(zhí)行一個方法時,就會在棧中創(chuàng)建一個棧幀入棧,方法結(jié)束后,該棧幀出棧??聪旅娴膱D解:
2、堆:堆內(nèi)存用來存儲對象和數(shù)組。數(shù)組以及所有new出來的對象都存儲在堆內(nèi)存中。在JVM中只有一個堆,所以堆是被所有線程共享的。 3、方法區(qū):方法區(qū)也是所有線程共享的區(qū)域,主要存儲靜態(tài)變量、常量池等。 三、數(shù)據(jù)在內(nèi)存中的存儲:1、基本類型的存儲:
先創(chuàng)建一個age變量,存儲在棧幀中的局部變量表,然后查找棧中是否有字面量值為6的內(nèi)容,如果有,直接把age指向這個地址,沒有開辟內(nèi)存空間來存儲"6"這個內(nèi)容,同時讓age指向它。當(dāng)創(chuàng)建grade變量時,因為已經(jīng)有字面量為"6"的內(nèi)容了,所以直接拿過來用。所以棧中的數(shù)據(jù)在當(dāng)前線程下是共享的。上面的代碼在內(nèi)存中的圖解如下: 如果給age重新賦值:
難么就會在棧中查找是否有字面量為"10"的內(nèi)容,有就直接拿來用,沒有就開辟內(nèi)存空間存儲"10",然后age指向這個10。所以基本類型的變量,變量值本身是不會改變的,重新賦值后,只是指向了新的引用而已。
調(diào)用:
在內(nèi)存中的存儲圖解:
2、引用類型的存儲:通過上圖可以發(fā)現(xiàn),執(zhí)行
時分兩個過程:
定義變量時,會在棧中開辟內(nèi)存空間存放user變量;賦值時會在堆內(nèi)存中開辟內(nèi)存空間存儲User實例,這個實例會有一個地址值,同時把這地址值賦給棧中的user變量。所以引用類型的變量名存儲在棧中,變量值存儲的是堆中相對應(yīng)的地址值,并不是存儲的實際內(nèi)容。 四、參數(shù)傳遞問題:關(guān)于參數(shù)的傳遞,可能有點難理解,到底是值傳遞還是引用傳遞?下面一起來學(xué)習(xí)一下:
執(zhí)行結(jié)果如下: 從結(jié)果可以發(fā)現(xiàn),name和age在方法調(diào)用后并沒有改變,所以傳入方法的只是實參的拷貝。
測試:
結(jié)果如下: 可以看到在方法內(nèi)對user重新賦值,直接影響這個對象,所以方法執(zhí)行完畢后輸出的是修改后的user。 對上面的測試方法稍作修改:
執(zhí)行結(jié)果如下: 結(jié)果卻是,方法執(zhí)行后的user竟然沒改變。 分析一下這兩次的執(zhí)行過程:第一次: 第一次執(zhí)行過程如上圖,main方法進(jìn)棧后,在堆中new了一個user對象x0001,然后調(diào)用userTest方法,userTest方法進(jìn)棧,并且把user對象的地址值x0001傳入userTest方法,所以在userTest方法中對user進(jìn)行操作直接影響地址值為x0001的對象。所以就出現(xiàn)了第一次運行結(jié)果。 第二次:
到了這里,又在堆中new了一個user對象x0002,然后讓棧中user變量指向新的user對象的地址值x0002。所以接下來在方法中對user的操作都是對地址值為x0002的對象的操作,自然不會影響到地址值為x0001的對象。所以就出現(xiàn)了第二次的運行結(jié)果。 小結(jié):由上面的案例可以得出結(jié)論,基本類型傳的是值的副本,引用類型傳的是地址值,所以不論傳的是引用類型還是基本類型,其實都是值傳遞。 |
|