Java千百問_05面向物件(011)_引用傳遞和值傳遞有什麼區別
阿新 • • 發佈:2019-01-07
1、什麼是值傳遞
值傳遞,是將記憶體空間中某個儲存單元中存放的值,傳送給另一個儲存單元。(java中的儲存單元並不是實體記憶體的地址,但具有相關性)
例如:
//定義了一個改變引數值的函式
public static void changeValue(int x) {
x = x *2;
}
public class TestMain{
//呼叫該函式
int num = 5;
System.out.println(num);
changeValue(num);
System.out.println(num);
}
結果如下:
5
5
呼叫函式changeValue()前後num的值都沒有改變。具體過程如圖:
- num作為引數傳遞給changeValue(int x)方法時,首先在記憶體空間中為x變數分配一個儲存單元(我們說x指向這個儲存單元)。
- 將記憶體空間中num指向的儲存單元中存放的值(即”5”),傳遞給了changeValue(int x)中的引數變數(即”x”),也就是把”5”傳給了x變數指向的儲存單元中。
- changeValue(int x)方法中對x變數的一切操作,都是針對x指向的儲存單元。與num指向的儲存單元沒有關係,當然也不會改變這個儲存單元中的值。
所以,值傳遞,傳遞的是儲存單元中的內容(8種基本型別:值,非基本型別:實際物件的地址)。
對於String來說JVM有他特殊的處理,瞭解更多看這裡: String在記憶體中如何存放
2、什麼是引用傳遞
java中只有值傳遞,沒有引用傳遞。
所謂的引用傳遞,只是一個錯誤的概念。
例如:
class person {
public static String name = "Jack";
//定義一個改變物件屬性的方法
public static void changeName(Person p) {
p.name = "Rose";
}
public static void main(String[] args) {
//定義一個Person物件,person是這個物件的引用
Person person = new Person();
//先顯示這個物件的name屬性
System.out.println(person.name);
//呼叫changeName(Person p)方法
changeName(person);
//再顯示這個物件的name屬性,看是否發生了變化
System.out.println(person.name);
}
}
執行後結果:
Jack
Rose
從結果看,方法用了一個物件引數,操作引數就可以改變傳入物件。我們的對引用傳遞的錯誤觀念這麼認為:
該物件複製了一個引用副本,傳給呼叫方法的引數,使得該方法可以對這個物件進行操作。
這種觀念是初學者常犯的錯誤。
實際上過程如圖:
- main方法中new了一個物件Person,儲存空間中實際分配了兩個物件:新建立Person類的實體物件、指向該物件的引用變數person。
其中,實體物件存放在堆記憶體中,引用變數存放在棧記憶體(Java儲存特性)。
瞭解更多java儲存看這裡: - 引用變數person指向的棧記憶體中,存放的是堆中實體物件的邏輯地址。
- 呼叫changeName(Person p)方法,將person引用變數傳入該方法引數p中(按照值傳遞,傳遞的是:實體物件的邏輯地址)。此時,changeName方法中對p的操作,與person沒有關係。
- changeName方法中,是對p指向的儲存單元中的值(即實體物件的邏輯地址)所指向的實體物件進行操作。直接改變了該實體物件。
- 由於person指向的儲存單元中的值也是該實體物件的邏輯地址,這個實體物件已經在第4步中被改變了。所以有上面的結果。
3、引用傳遞和值傳遞有什麼區別
引用傳遞是個偽概念,java中只有值傳遞。