本篇為記錄不同的Java資料型態在記憶體中的變化情形,參考JVM 的 Stack 和 Heap並重點摘要。
Java語言中,資料型別分為基本型別及參考(類別)型別2種,特性如下:
byte、short、int、long、float、double、boolean、char特性:
不屬於基本型別的,都屬於此類別,這種類型通常都需要用 new 去創建,如 User user = new User("Mark"); 。特性:

儲存函數路徑及區域變數。變數a的123。函數路徑:Stack 內的變數值為物件實體在 Heap 中回傳所在的記憶體位址,如上圖的0x1234。後進先出 (FILO) 的容器,具有存取速度快和管理簡單的特點。下往上堆,如圖b在a上面。區域變數只能存在methods中),所以由系統自行去產生和回收空間即可,不用特別設計垃圾回收機制。物件實體的屬性資料,如圖中的name :Mark,並產生位址:0x1234。記憶體位址給stack。沒有立即給值的情況下,也是要等new一個該類別的物件實體,才會在heap中建立該物件的值,並把預設值存放進去,之後再把記憶體位址給stack。共享資料,所以同 Process 底下的其他 Thread 也可以進行存取。Garbage Collection 機制,因為無法掌握物件實體的生命週期,所以存取速度慢,但是GC是否有提升效能的部分還是有待討論。兩個物件實體:當a物件 = b物件,代表b物件在stack中只是把heap的位址給a物件。
兩個區域變數:a = b,代表區域變數b在stack中把區域變數a的值給覆蓋。
運作如下圖

當在heap中沒被參考到的物件,也就是沒有變數儲存他的位址(如上圖0x12),就由JVM的GC機制回收並釋放記憶體空間。
參數使用基本型別跟類別型別的差異: static void passValue(double value) {
value = 20.0;
}
static void passReference(Pen reference) {
reference.price = 20.0;
}
public static void main(String[] args) {
double price = 10.0;
passValue(price);
System.out.println(price); // 10
Pen myPen = new Pen();
myPen.price = 10.0;
passReference(myPen);
System.out.println(myPen.price); // 20
}
解:
當資料為基本型別時:
price 值為10.0的空間。passValue調用該值成為該方法的參數時,會在stack再建立一個空間儲存該參數(value)的值10.0。value被賦予新的值20.0。passValue運作結束,區域變數value的生命週期也結束了。price還是一樣沒有變化為10.0。當資料為類別型別時:
price 值為10.0的空間,並回傳位址0x12給stack並儲存在變數myPen。passReference調用該值(位址0x12)成為該方法的參數時,會在stack再建立一個空間儲存該參數(reference)的值0x12。reference的屬性price 值在heap中會被更改為20.0。passReference運作結束,區域變數reference的生命週期也結束了。myPen因為屬性price 的值在heap中已經被更改為20.0,所以最後print出來的值就變為20.0。
參考資料:
JVM 的 Stack 和 Heap:https://blog.marklee.tw/java-interview-jvm-stack-heap/