從我實(shí)習(xí)面試開始就有在面試中遇到過這個(gè)問題:Java是值傳遞還是引用傳遞决乎?
當(dāng)時(shí)的我只會背背面試題队询,但是網(wǎng)上的答案有些還是錯(cuò)的,導(dǎo)致我決心寫這一篇文章构诚。
雖然網(wǎng)上已經(jīng)有很多文章珠玉在前蚌斩,但是我還是想寫一篇我自己的文章,如果寫的不好范嘱,請見諒
文章開始之前我們還是來解答Java是值傳遞還是引用傳遞送膳?
這個(gè)問題吧!答案自然是:Java是值傳遞
給定結(jié)論后我們再來解釋一下什么叫 值傳遞&引用傳遞
值傳遞:值傳遞是指在調(diào)用函數(shù)時(shí)將實(shí)際參數(shù)復(fù)制一份傳遞到函數(shù)中丑蛤,這樣在函數(shù)中如果對參數(shù)進(jìn)行修改叠聋,將不會影響到實(shí)際參數(shù)。
引用傳遞:引用傳遞是指在調(diào)用函數(shù)時(shí)將實(shí)際參數(shù)的地址傳遞到函數(shù)中受裹,那么在函數(shù)中對參數(shù)所進(jìn)行的修改碌补,將影響到實(shí)際參數(shù)。
以下圖片來自百度百科
上代碼證明:
/**
* 證明java值傳遞demo
*
* @author miao
*/
public class PassValueDemo {
public static void main(String[] args) {
int a = 1;
String str = "1";
User user = new User("阿花", 6);
System.out.println("調(diào)用方法前a為:" + a);
System.out.println("調(diào)用方法前str為:" + str);
System.out.println("調(diào)用方法前user為:" + user);
System.out.println("------------------------------------------");
convert(a, str, user);
System.out.println("------------------------------------------");
System.out.println("調(diào)用方法后a為:" + a);
System.out.println("調(diào)用方法后str為:" + str);
System.out.println("調(diào)用方法后user為:" + user);
}
private static void convert(int a, String str, User user) {
a = 2;
str = "2";
user.setAge(9);
user.setUsername("大壯");
System.out.println("調(diào)用方法中a為:" + a);
System.out.println("調(diào)用方法中str為:" + str);
System.out.println("調(diào)用方法中user為:" + user);
}
}
/**
* @author miao
*/
class User {
public String username;
public int age;
public User(String username, int age) {
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
程序的執(zhí)行結(jié)果:
調(diào)用方法前a為:1
調(diào)用方法前str為:1
調(diào)用方法前user為:User{username='阿花', age=6}
------------------------------------------
調(diào)用方法中a為:2
調(diào)用方法中str為:2
調(diào)用方法中user為:User{username='大壯', age=9}
------------------------------------------
調(diào)用方法后a為:1
調(diào)用方法后str為:1
調(diào)用方法后user為:User{username='大壯', age=9}
我們可以看到棉饶,身為基本類型的int和被final修飾的String并沒有改變厦章,但是引用類型User改變了,所以砰盐,網(wǎng)上就有人得出了結(jié)論:java針對基本類型是值傳遞闷袒,對于引用類型是引用傳遞
。但是Q沂帷D抑琛;卧瘛!這是錯(cuò)誤的結(jié)論也物,不相信的話宫屠,我在上面的代碼中加一行代碼,就知道為什么這個(gè)是錯(cuò)的結(jié)論了
在convert()方法中str = "2";
下面增加一行user = new User("小美", 18)
滑蚯,讓我們看看這樣的結(jié)果是什么浪蹂?
程序的執(zhí)行結(jié)果:
調(diào)用方法前a為:1
調(diào)用方法前str為:1
調(diào)用方法前user為:User{username='阿花', age=6}
------------------------------------------
調(diào)用方法中a為:2
調(diào)用方法中str為:2
調(diào)用方法中user為:User{username='大壯', age=9}
------------------------------------------
調(diào)用方法后a為:1
調(diào)用方法后str為:1
調(diào)用方法后user為:User{username='阿花', age=6}
從上述結(jié)果可以看出,當(dāng)我們在 convert
方法中添加 user = new User("小美", 18)
之后告材,“引用傳遞”就突然變值傳遞了坤次?為什么?
這是因?yàn)椋?strong>在 Java 語言中本質(zhì)上只有值傳遞斥赋,也就說 Java 的傳參只會傳遞它的副本缰猴,并不會傳遞參數(shù)本身。
即傳入convert()時(shí)的user為 User user
的副本疤剑,指向同一個(gè)new User("阿花", 6)
的堆地址滑绒,
當(dāng)執(zhí)行user = new User("小美", 18)
時(shí),指向的堆內(nèi)存改變了隘膘,所以再進(jìn)行任何操作都跟之前的堆地址沒關(guān)系了疑故,即證實(shí)了,傳遞的是一個(gè)副本弯菊。
未執(zhí)行user = new User("小美", 18)
之前
執(zhí)行user = new User("小美", 18)
之后
總結(jié):通過本文的內(nèi)容纵势,我們可以得出:在 Java 語言中只有值傳遞,方法傳參時(shí)只會傳遞副本信息而非原內(nèi)容误续。我們還知道了基礎(chǔ)數(shù)據(jù)類型會直接生成到棧上吨悍,而對象或數(shù)組則會在棧和堆上都生成信息,并將棧上生成的引用蹋嵌,直接指向堆中生成的數(shù)據(jù)