java中的值傳遞
我們都知道,在java中,簡單的swap交換兩個對象是行不通的,對于基本數(shù)據(jù)類型這很好理解,因為方法上的參數(shù)是值的復制,就是很好理解的那種值傳遞。但是如果是交換兩個對象該如何理解呢?
@Data
public class Number {
private Integer num;
public Number(Integer n) {
this.num = n;
}
}
public static void main(String[] args) {
Number n1 = new Number(1);
System.out.println(n1);
changeNum(n1);
System.out.println(n1);
setNum(n1);
System.out.println(n1);
}
public static void setNum(Number number) {
number.setNum(999);
}
public static void changeNum(Number number) {
number = new Number(111);
}
在探究問題之前,先來了解概念:
值傳遞: 值傳遞指的是在函數(shù)調(diào)用的時候?qū)?shù)復制一份,這樣在函數(shù)中的操作就對實際的參數(shù)沒有影響;
引用傳遞:引用傳遞是將參數(shù)的地址傳入函數(shù)操作,這樣在函數(shù)操作的時候就會改變實際參數(shù);
所以值傳遞較引用傳遞的區(qū)別是:
值傳遞會創(chuàng)建一個副本(復制一份),而引用傳遞不會創(chuàng)建副本;
接下來注意,由于上述的區(qū)別,造成的兩者的不同是:
創(chuàng)建了副本的不會對原副本造成影響,而沒有創(chuàng)建副本的會對元數(shù)據(jù)有影響;
那么我們區(qū)分值傳遞還是引用傳遞的根本是看它到底有沒有復制副本;而會不會對實際參數(shù)造成影響是有沒有創(chuàng)建副本帶來的后果;
接下來看上面的代碼:
為什么setNum()可以改變對象的值,而changeNum()卻不行呢?因為java并不是簡單的把對象復制了一份傳入函數(shù),而是將對象的引用復制了一份傳入函數(shù)。也就是說在函數(shù)調(diào)用的時候,實際對象還是只有一個,但是它有2個引用,一個是本身的引用,另一個是調(diào)用函數(shù)的時候引用的復制,這2個引用都指向這個對象。所以就造成了上述情況。
setNum()的內(nèi)部實際操作是改變屬性,引用是沒有屬性的,要改變的是引用指向的對象的屬性,他們指向的是同一個對象,那這個操作就會修改實際對象。
changeNum()就不一樣了,它做的是改變引用的指向,但是這個引用并不是原來實際對象的引用,而是一個復制的引用,復制的引用出了函數(shù)就不存在了,所以不會對實際對象有所改變;
最后在回到開始的問題: 為什么java是值傳遞?這里答案已經(jīng)很明顯了,java對參數(shù)的處理是復制了一份實際參數(shù)的引用,而值傳遞的特點就是會復制一個副本,所以這就是值傳遞,只不過有點特殊(沒有直接復制參數(shù));也許你還會說: 它傳遞的就是一個引用啊,只不過是復制過的引用,也是引用啊,這是引用傳遞。這里就突出了一個概念的重要性,不是說傳遞的是引用就是引用傳遞,而是看概念,既然它創(chuàng)建了一個副本,這就不符合引用傳遞的概念,所以從概念上說,這時值傳遞。不過要是拋開概念,要說是引用傳遞也沒有什么問題,但是概念不就是讓人不那么混淆而存在的嘛,既然已經(jīng)有了定義,遵守它就好了。