# 傳值Call by value;傳址
## Call by value
```JAVA=
public class CallByVal {
public static void main(String[] args) {
int a = 10, b = 15;
System.out.println("傳值前呼叫\\t a= " + a + " \\t b= " + b);
byVal(a, b);
System.out.println("傳值前呼叫\\t a= " + a + " \\t b= " + b);
}
static void byVal(int x, int y) {
int t;
t = x;
x = y;
y = t;
System.out.println("傳值前呼叫\\t x= " + x + " \\t y= " + y);
}
}
```
共在stack區產生四格空間,
a,b,x,y ,
一開始先放a=10,b=15,
再來x=10,y=15,
之後對調變成x=15,y=10,
最後印出數值a,b不變。
## Call by reference
```JAVA=
class Obj {
int a, b;
Obj() {
a = 10;
b = 15;
}
}
public class CallByRef {
public static void main(String[] args) {
Obj obj = new Obj();
System.out.println("傳值前呼叫\t a= " + obj.a + " \t b= " + obj.b);
byRef(obj);
System.out.println("傳值前呼叫\t a= " + obj.a + " \t b= " + obj.b);
}
static void byRef(Obj p) {
int t;
t = p.a;
p.a = p.b;
p.b = t;
}
}
```
一開始從main開始執行(11行),當new物件時,會同時呼叫ojb()方法的建構式,
來初始化物件,將obj物件的a,b初始化為10,15。
這時候stack會配置一個空間用來放置obj物件實體的參考位置,heap區塊則會配置一個空間放置obj物件實體。
之後13行印出呼叫未傳址之前的結果obj.a=10,obj.b=15。
14行呼叫byRef(Obj p)方法,會將obj()物件實體的記憶體位置(實引數-引用)a,b傳給byRef()方法的虛引數p,此時實引數和虛引數會占用相同記憶體位置,在這時若更改虛引數會影響到實引數。
14行呼叫時,會執行18-22行的程式區塊,讓p.a和p.b互換,p.a=15,p.b=10,等同於把obj.a,obj.b的值互換,所以obj.a=15,obj.b=10。
總共在stack建立了兩個區塊,obj和p,分別記錄obj和p的記憶體位置,對應heap區塊的物件實體位置。
在heap建立了兩個區塊,a和b是obj和p物件變數的屬性,Heap區塊上的屬性對應到stack區塊obj和p物件變數的記憶體位置。
```
Obj obj = new Obj();
obj是物件變數
Obj()是class名
byRef(Obj p)
p是物件變數
stack區塊中的記憶體位置也就是值。指向heap物件的記憶體位置
```
宣告在方法內的變數稱為區域變數。
區域變數存放在stack區塊中,又稱stack variable,方法一結束該變數就從記憶體中消失,也稱為自動變數,automatic variables。
* 物件型式的變數存放的是該物件的"記憶體位置"(stack區塊)
* 基本型別的變數存放的是實際上的"值"(stack區塊)
```=java
public static void mani (String []args){
int a =1;
Employee emp = new Employee();
emp.name= "V";
emp.empno= 1;
}
```
* stack區塊存了0800記憶體位置和1這個值
* heap區塊存放Employee 這個類別class的區塊,0800指向Employee這整個類,對應到當中的name=V; empno=1;
```=java
public static void main (String []args){
Employee emp = new Employee();
emp.name= "V";
emp.empno= 1;
Employee emp2 = new Employee();
emp.name= "D";
emp2.empno= 2;
System.out.println(emp==emp2);
}
```
* 多新增emp2變數,產生stack區記憶體位置0900,但還是指向Employee物件,不過是新的heap區,內含name= D;empno=2;
```
Employee emp2 = new Employee();
emp2.empno= 2;
```
* ==比較stack區塊中存放的值(記憶體位置)是否一樣,而emp,emp2存放的是記憶體位置0800,0900,因此記憶體位置不同,輸出false。
```
emp2 = emp;
```
* 輸出前再加一句emp2 = emp;
* emp的0800複製給emp2,emp2也變0800,所以釋放原本0900對應再heap區塊的Employee區塊,清除資料、釋放記憶體。
* 當main方法結束時,會清除main方法程式區塊用到stack區變數的"記憶體",造成heap區的物件沒被參考到(沒被指向),所以heap區記憶體也會被回收。