Call by value

Prerequisites:

一進入方法,若引數是物件,也就是記憶體位址,參數複製傳進來的引數,稱為Call by value。

修改成員變數

以下的程式碼要傳遞testClz變數給copyAddress()方法。

TestClz

1
2
3
class TestClz {
  public int age;
}

Test

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test {
  public static void main(String[] args) {
    Test test = new Test();
    TestClz testClz = new TestClz();
    testClz.age = 50;
    // 把testClz傳進copyAddress()
    test.copyAddress(testClz);
    System.out.println(testClz.age);
  }
  public void copyAddress(TestClz arg1) {
    arg1.age = 100;
  }
}

「複製」testClz變數「記憶體位址」給arg1變數(參考下圖)。

  • arg1存的0x0033
  • testClz變數存的0x0033

img

arg1存的0x0033與testClz變數存的0x0033一樣,所以修改arg1.age,也就是修改0x0033記憶體位址中的物件。

1
arg1.age = 100;

執行結果為100

100

參數設成新的記憶體位址

TestClz

1
2
3
class TestClz {
  public int age;
}

Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {
  public static void main(String[] args) {
    Test test = new Test();
    TestClz testClz = new TestClz();
    testClz.age = 50;
    test.copyAddress(testClz);
    System.out.println(testClz.age);
  }
  public void copyAddress(TestClz arg1) {
    // 參數設成新的記憶體位址
    arg1 = new TestClz();
    arg1.age = 60;
  }
}

參數arg1存其它記憶體位址。

1
arg1 = new TestClz();

arg1存的0x0066與testClz變數存的0x0033不一樣,所以修改arg1.age,也就是修改0x0066記憶體位址中的物件,而不是修改0x0033記憶體中的物件。

img

執行結果是50

50

執行完copyAddress()方法後,參數arg1就會被記憶體釋放,包含0x0066也會被記憶體釋放,所謂的記憶體釋放就是把arg1設為null,JVM發現有變數指向null,就會把這個變數刪掉,不浪費記憶體空間。

下圖中,離開copyAddress()方法後,Stack堆疊已經沒有arg1參數,Heap堆也沒有0x0066。

img

此處是「複製記憶體位址」到「參數」中,並非「指向」記憶體位址,跟C++的call by addresscall by reference完全不同的概念。

畫圖檔案名稱為func_copy_address.drawio

results matching ""

    No results matching ""