流言終結者:Java是引用傳遞還是值傳遞?

流言終結者:Java是引用傳遞還是值傳遞?

前言

今天聊一個很小的話題,引用傳遞和值傳遞。為什麼拉出這個話題呢?因為自己太菜吧…在這上邊栽了跟頭。所以今天就聊一聊Java中是引用傳遞還是值傳遞。

正文

小A:MDove,我有一個疑問:Java的方法中是引用傳遞還是值傳遞呢?

MDove:想要解答這個問題,我們需要先明確一個問題:那就是引用傳遞和值傳遞的區別。咱們先看倆行代碼:

int count = 66;
String str = "MDove";
流言終結者:Java是引用傳遞還是值傳遞?

如圖,int是基本類型,66直接保存在變量count中。而對於引用類型來說,變量存的是實例對象的地址,如上圖也畫的0x10一樣,它指向實例對象。一般稱這種變量為"引用"。對於我們的String str = "MDove"來說,str就是這個引用,這個引用指向了"MDove"。

小A:這個我明白,可以這個對於我的問題又有什麼幫助呢?

MDove:彆著急,且聽我慢慢道來。說了基本類型和引用類型。咱們再來聊一聊我們日常開發中極為常見的符號:=。

小A:=?不就是賦值符號麼。

MDove:沒錯,的確是賦值。咱們來看一下,賦值符號對於基本類型和引用類型的不同之處。再看一段代碼:

int count = 66;
count = 666;
String str = "MDove";
str = "MDove is cool.";
流言終結者:Java是引用傳遞還是值傳遞?

由上圖,我們可以看出,對於基本類型來說,count = 666;是直接進行賦值。而str = "MDove is cool.";則是重新開闢了一塊空間,然後將這塊空間的地址賦值給str變量(引用)。

小A:這個我知道呀!

MDove:彆著急,接下來咱們來看一下值傳遞的情況。

小A:不用麻煩,我知道,基本類型就是值傳遞,比如這樣的:

int count = 66;
fun(count);
private void fun(int count){
count = 666;
}

因為是值傳遞,所以在fun(int coount)中,count只是正真變量的拷貝,因此count = 666;也是對拷貝進行賦值,因此執行完了fun方法,我們的count還是等於66。

MDove:沒錯,那我們在換一個例子,把基本類型改為引用類型:

String str = "MDove";
fun(str);

private void fun(String str){
str = "MDove is cool.";
}

如果我們在fun之後打印str,答案是什麼?

小A:我知道答案呀!正是因為我知道答案,所以我才疑惑,答案還是"MDove"(因為你本來就不cool)。按我的理解方法參數都是引用類型了,那應該是引用傳遞,內部str賦值應該會影響外邊才對啊!

MDove:這裡糾正你一個問題,不是參數是引用類型,它就是引用傳遞。其實上面這個例子也恰恰應徵了這個問題,引用類型同樣也是值傳遞。因此fun參數的str,依然是一個拷貝,因此此時的賦值對面來說沒有任何意義。其中,IDE也幫我們證實了這個問題,讓我們看一張截圖:

流言終結者:Java是引用傳遞還是值傳遞?

仔細看一下它們的顏色,灰色的。說明什麼?說明它們沒有被使用。如果真的是引用傳遞,那麼str不會是灰色的。

小A:可是不對呀!如果是這種寫法,就改變了變量的值了:

流言終結者:Java是引用傳遞還是值傳遞?

MDove:這樣當然能改變值,對於引用變量來說,值傳遞,拷貝了它的引用,但是它的這份拷貝的引用所指向的真實地址是沒變的。上述的操作畫成圖是這個樣子:

流言終結者:Java是引用傳遞還是值傳遞?

這樣是不是隱隱約約能夠明白點了?

小A:哦,好想有點感覺了。雖然我fun內的mDove是拷貝的,但是它指向的真正地址是真實的。所以我通過這個拷貝的引用仍然修改了它真實的變量地址。

MDove:沒錯,正解。那你這個理解了。是不是對於Java是引用傳遞還是值傳遞這個問題就有了明確的答案了?!

尾聲

這裡總結倆個誤區:

  • 1、Java是引用傳遞。(這是錯誤的,上述的內容恰恰說明Java是值傳遞)
  • 2、參數類型是什麼就是什麼傳遞。(這是什麼邏輯….)


分享到:


相關文章: