前言
今天,想和大家聊聊關(guān)于java中的參數(shù)傳遞的原理,參數(shù)的傳遞有兩種,值傳遞和引用傳遞。
-
值傳遞:是指在調(diào)用函數(shù)時將實(shí)際參數(shù)復(fù)制一份傳遞到函數(shù)中,這樣在函數(shù)中如果對參數(shù)進(jìn)行修改,將不會影響到實(shí)際參數(shù)。
-
引用傳遞:是指在調(diào)用函數(shù)時將實(shí)際參數(shù)的地址傳遞到函數(shù)中,那么在函數(shù)中對參數(shù)所進(jìn)行的修改,將影響到實(shí)際參數(shù)。
基本類型傳遞
先來看看下面這段最基本的代碼:
@Test
public void test() {
int n = 10;
test01(n);
System.out.println("最終結(jié)果n==" + n);
}
private void test01(int m) {
System.out.println("修改之前m==" + m);
m = 20;
System.out.println("修改之后m==" + m);
}
輸出結(jié)果:
修改之前m==10
修改之后m==20
最終結(jié)果n==10
如果跟你預(yù)期的不同,那我想你還是沒有理解參數(shù)的值傳遞與引用傳遞的原理。
結(jié)合生活中的場景,深入理解一下值傳遞和引用傳遞:
你有一把鑰匙,當(dāng)你的朋友想要去你家的時候,如果你直接把你的鑰匙給他了,這就是引用傳遞。這種情況下,如果他對這把鑰匙做了什么事情,比如他在鑰匙上刻下了自己名字,那么這把鑰匙還給你的時候,你自己的鑰匙上也會多出他刻的名字。
你有一把鑰匙,當(dāng)你的朋友想要去你家的時候,你復(fù)刻了一把新鑰匙給他,自己的還在自己手里,這就是值傳遞。這種情況下,他對這把鑰匙做什么都不會影響你手里的這把鑰匙。
下面我們來畫圖更好的理解上述代碼的例子:
當(dāng)發(fā)生函數(shù)調(diào)用的時候 n
將自己傳入到 test01
方法中,同時將自己的值復(fù)制了一份并賦值給了一個新變量 m
從圖中可以看出這是 n
和 m
兩個變量沒有一毛錢關(guān)系(m只是n的復(fù)制品),所以對 m
的修改并不會影響到 n
。
如果想要改變n
的值,可以使用方法的返回值:
n = test01(n);
引用類型傳遞
下面來看看引用類型的傳遞:
public class Dog {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dog(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
}
@Test
public void test() {
Dog dog1 = new Dog("小白");
test01(dog1);
System.out.println("最終結(jié)果dog==" + dog1);
}
private void test01(Dog dog) {
System.out.println("修改之前 dog==" + dog);
dog.setName("小黑");
System.out.println("修改之后 dog==" + dog);
}
輸出結(jié)果:
修改之前 dog==Dog{name='小白'}
修改之后 dog==Dog{name='小黑'}
最終結(jié)果dog1==Dog{name='小黑'}
為了方便大家理解,還是畫圖來分析一下:
在 test
方法中我們創(chuàng)建了一個 dog1
的對象,該對象存放于堆內(nèi)存中,假設(shè)內(nèi)存地址為 0x1120
,于是 dog1
這個變量便應(yīng)用了這塊內(nèi)存地址。
當(dāng)我們調(diào)用 test01
這個方法的時候會在該方法棧中創(chuàng)建一個變量 dog
,這個 dog
變量是由原本的入?yún)?dog1
復(fù)制而來,所以它所對應(yīng)的堆內(nèi)存依然是 0x1120
;
所以當(dāng)我們通過 dog
這個變量修改了數(shù)據(jù)后,本質(zhì)上修改的是同一塊堆內(nèi)存中的數(shù)據(jù)。從而原本引用了這塊內(nèi)存地址的 dog1
也能查看到對應(yīng)的變化。
如果不理解上面的話,那么記住下面的兩句話就行了:
傳遞引用類型的數(shù)據(jù)時,傳遞的并不是引用本身,依然是值;只是這個值是內(nèi)存地址罷了。
因?yàn)榘严嗤膬?nèi)存地址傳過去了,所以對數(shù)據(jù)的操作依然會影響到外部。
那我們繼續(xù)看看下面的代碼,這種情況能否改變參數(shù)的值
@Test
public void test() {
Dog dog1 = new Dog("小白");
test01(dog1);
System.out.println("最終結(jié)果dog1==" + dog1);
}
private void test01(Dog dog) {
System.out.println("修改之前 dog==" + dog);
dog = new Dog("小黑");
System.out.println("修改之后 dog==" + dog);
}
輸出結(jié)果:
修改之前 dog==Dog{name='小白'}
修改之后 dog==Dog{name='小黑'}
最終結(jié)果dog1==Dog{name='小白'}
假設(shè) Java
是引用傳遞那最終的結(jié)果應(yīng)該是打印 小黑
才對,從結(jié)果看這里依然是值傳遞。
還是畫圖來分析一下:
如果是引用傳遞,原本的 0x1120
應(yīng)該是被直接替換為新創(chuàng)建的 0x1121
才對;而實(shí)際情況如上圖所示,dog
直接重新引用了一個對象dog = new Dog("小黑")
,兩個對象之間互不干擾。文章來源:http://www.zghlxwxcb.cn/news/detail-427905.html
總結(jié)
Java中參數(shù)傳遞其實(shí)還是值傳遞的,只不過對于引用類型參數(shù),值的內(nèi)容是對象的引用。文章來源地址http://www.zghlxwxcb.cn/news/detail-427905.html
到了這里,關(guān)于深入淺出Java中參數(shù)傳遞的原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!