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
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記憶體中的物件。
執行結果是50
50
執行完copyAddress()方法後,參數arg1就會被記憶體釋放,包含0x0066也會被記憶體釋放,所謂的記憶體釋放就是把arg1設為null,JVM發現有變數指向null,就會把這個變數刪掉,不浪費記憶體空間。
下圖中,離開copyAddress()方法後,Stack堆疊已經沒有arg1參數,Heap堆也沒有0x0066。
此處是「複製記憶體位址」到「參數」中,並非「指向」記憶體位址,跟C++的call by address與call by reference完全不同的概念。
畫圖檔案名稱為func_copy_address.drawio