Java必踩的坑之方法中形參、實(shí)參傳遞
首先亮明Java中方法參數(shù)傳遞的規(guī)則,這兩點(diǎn)很重要:
- 如果實(shí)參是基本類型(包括包裝類型)或者String,則實(shí)參不會變(傳的是值);
- 如果實(shí)參是對象集合或者數(shù)組,則實(shí)參會改變(傳的是引用)。
上面這兩條比較簡單,筆者就不展開說了,這里只說一點(diǎn),關(guān)于方法中引用的傳遞,很多人會踩坑,如下:
我們先以數(shù)組舉例,如下代碼,很簡單的幾行,大家猜一下會最終輸出的結(jié)果是什么樣子的呢?
public class PassByValueDemo { public static void main(String[] args) { int[] i = {0}; new PassByValueDemo().Demo(i); // 這個(gè)地方還是0 System.out.printf(Arrays.toString(i)); } public void Demo(int[] i){ // 這個(gè)實(shí)參為數(shù)組,傳的是引用,其值會改變??? nonono,只是在這個(gè)方法中改變了,回到main方法棧中還是{0}。 i = new int[]{1,2,3}; System.out.println(Arrays.toString(i)); } }
根據(jù)第二條規(guī)則如果實(shí)參是對象集合或者數(shù)組,則實(shí)參會改變(傳的是引用),大家很容易想到,這個(gè)實(shí)參為數(shù)組,傳的是引用,其值會改變,那就大錯(cuò)特錯(cuò)了。這個(gè)只會在方法中短暫改變數(shù)組的值,回到main方法棧中還是{0}。
實(shí)際輸出如下:
[1, 2, 3]
[0]
Process finished with exit code 0
為什么會這樣呢?具體分析如下:
- 我們先看main方法中第一行操作int [] i ={0},這個(gè)操作會在內(nèi)存中開辟一個(gè)4字節(jié)大小的內(nèi)存空間,然后返回其該數(shù)組的首地址,我們假設(shè)該數(shù)組的首地址值為0x1111,那么此時(shí)i就指向了內(nèi)存中0x1111這么一個(gè)空間。內(nèi)存地址為0x1111的空間存儲了0;
- 繼續(xù)往下指看,調(diào)用Demo方法,此時(shí)會保存mian方法棧的狀態(tài),包括i在mian方法中指向的內(nèi)存空間,這里點(diǎn)很重要,很重要,重要,重要的事情說三遍。
- 在Demo方法中 new Int[] {1,2,3},這個(gè)操作會重新在內(nèi)存中開辟一個(gè)空間,然后返回該數(shù)組的首地址的值,我們把這個(gè)地址值假設(shè)為0x2222,內(nèi)存為0x2222存儲了1,2,3;此時(shí)i的值指向了0x2222;那么這個(gè)時(shí)候輸出i,當(dāng)然會打印1,2,3;
- 執(zhí)行完了Demo方法,我們回到main方法中,此時(shí)從虛擬機(jī)棧中恢復(fù)剛才進(jìn)入Demo方法前保存的棧信息,在進(jìn)入Demo方法前i是指向0x1111這么一個(gè)地址空間,進(jìn)入前已經(jīng)保存了棧中的局部變量表中(局部變量表可參考筆者該篇博文:點(diǎn)擊我),我們現(xiàn)在取出來,那么i的指向的就是0x1111,而不是0x2222,此時(shí)打印的是0x1111指向的值,也就是0;
雖然我們不能改變引用地址,但是可以改變引用指向的地址空間里的值,如下:
public class PassByValueDemo { public static void main(String[] args) { int[] i = {0}; new PassByValueDemo().Demo(i); System.out.printf(Arrays.toString(i)); } public void Demo(int[] i){ i[0] = 1; System.out.println(Arrays.toString(i)); } }
輸出結(jié)果:
[1]
[1]
Process finished with exit code 0
熟悉C或C++的同學(xué)可以類比int *const(允許更改存儲在地址中的值),而不是int const*(允許指針指向其他地址)。
Java 形參和實(shí)參的區(qū)別:
形參 :就是形式參數(shù),用于定義方法的時(shí)候使用的參數(shù),是用來接收調(diào)用者傳遞的參數(shù)的。 形參只有在方法被調(diào)用的時(shí)候,虛擬機(jī)才會分配內(nèi)存單元,在方法調(diào)用結(jié)束之后便會釋放所分配的內(nèi)存單元。 因此,形參只在方法內(nèi)部有效,所以針對引用對象的改動也無法影響到方法外。
實(shí)參 :就是實(shí)際參數(shù),用于調(diào)用時(shí)傳遞給方法的參數(shù)。實(shí)參在傳遞給別的方法之前是要被預(yù)先賦值的。 在本例中 swap 方法 的numa, numb 就是形參,傳遞給 swap 方法的 a,b 就是實(shí)參
注意:在值傳遞調(diào)用過程中,只能把實(shí)參傳遞給形參,而不能把形參的值反向作用到實(shí)參上。在函數(shù)調(diào)用過程中,形參的值發(fā)生改變,而實(shí)參的值不會發(fā)生改變。而在引用傳遞調(diào)用的機(jī)制中,實(shí)際上是將實(shí)參引用的地址傳遞給了形參,所以任何發(fā)生在形參上的改變也會發(fā)生在實(shí)參變量上。
總結(jié)
到此這篇關(guān)于Java必踩坑之方法中形參、實(shí)參傳遞的文章就介紹到這了,更多相關(guān)Java形參、實(shí)參傳遞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA SpringBoot:Cannot resolve configuration&
這篇文章主要介紹了IDEA SpringBoot:Cannot resolve configuration property配置文件問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07詳解如何讓Spring MVC顯示自定義的404 Not Found頁面
這篇文章主要介紹了詳解如何讓Spring MVC顯示自定義的404 Not Found頁面,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10java中的通用權(quán)限管理設(shè)計(jì)(推薦)
下面小編就為大家推薦一篇java中的通用權(quán)限管理設(shè)計(jì),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12Java 并發(fā)編程學(xué)習(xí)筆記之Synchronized底層優(yōu)化
這篇文章主要介紹了Java 并發(fā)編程學(xué)習(xí)筆記之Synchronized底層優(yōu)化的相關(guān)資料,主要包含了重量級鎖,輕量級鎖,偏向鎖和其他優(yōu)化等方面,有需要的小伙伴可以參考下2016-05-05java 關(guān)鍵字static詳細(xì)介紹及如何使用
這篇文章主要介紹了java 關(guān)鍵字static詳細(xì)介紹及如何使用的相關(guān)資料,需要的朋友可以參考下2017-03-03