1. 程式人生 > >Java千百問_05面向物件(011)_引用傳遞和值傳遞有什麼區別

Java千百問_05面向物件(011)_引用傳遞和值傳遞有什麼區別

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的值都沒有改變。具體過程如圖:

這裡寫圖片描述

  1. num作為引數傳遞給changeValue(int x)方法時,首先在記憶體空間中為x變數分配一個儲存單元(我們說x指向這個儲存單元)。
  2. 將記憶體空間中num指向的儲存單元中存放的值(即”5”),傳遞給了changeValue(int x)中的引數變數(即”x”),也就是把”5”傳給了x變數指向的儲存單元中。
  3. 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

從結果看,方法用了一個物件引數,操作引數就可以改變傳入物件。我們的對引用傳遞的錯誤觀念這麼認為:
該物件複製了一個引用副本,傳給呼叫方法的引數,使得該方法可以對這個物件進行操作。
這種觀念是初學者常犯的錯誤。

實際上過程如圖:

這裡寫圖片描述

  1. main方法中new了一個物件Person,儲存空間中實際分配了兩個物件:新建立Person類的實體物件、指向該物件的引用變數person
    其中,實體物件存放在堆記憶體中,引用變數存放在棧記憶體(Java儲存特性)。
    瞭解更多java儲存看這裡:
  2. 引用變數person指向的棧記憶體中,存放的是堆中實體物件的邏輯地址
  3. 呼叫changeName(Person p)方法,將person引用變數傳入該方法引數p中(按照值傳遞,傳遞的是:實體物件的邏輯地址)。此時,changeName方法中對p的操作,與person沒有關係
  4. changeName方法中,是對p指向的儲存單元中的值(即實體物件的邏輯地址)所指向的實體物件進行操作。直接改變了該實體物件。
  5. 由於person指向的儲存單元中的值也是該實體物件的邏輯地址,這個實體物件已經在第4步中被改變了。所以有上面的結果。

3、引用傳遞和值傳遞有什麼區別

引用傳遞是個偽概念java中只有值傳遞