# 傳值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區記憶體也會被回收。