我們常說的Java內存主要分爲四大塊(寄存器不在考慮之內,我們無法用代碼來操控它):stack(棧)、heap(堆)、data segment(數據區)、code segment(代碼區)。它們的主要用途如下圖所示:
而在上面四個當中,我們經常談論的是右邊那兩個傢伙——stack和heap。今天我們就來聊聊Java代碼在運行的過程中,在stack和heap中到底是什麼樣子的吧。
我們先看下面一段代碼:
- public static void main(String[] args) {
- TestReference testReference = new TestReference();
- int age = 1;
- Person xiaoqiang = new Person("小強", 21);
- Person xiaoming = new Person("小明", 22);
- testReference.selfPlus(age);
- System.out.println("age經過selfPlus方法的處理後爲:" + age);
- testReference.changeName(xiaoqiang);
- System.out.println("小強經過changeName方法的處理後的名字爲:" + xiaoqiang.getName());
- testReference.changeAge(xiaoming);
- System.out.println("小明經過changeAge方法的處理後的年齡爲:" + xiaoming.getAge());
- }
- public void selfPlus(int i) {
- i = i + 1;
- }
- public void changeName(Person person) {
- person = new Person("小剛");
- }
- public void changeAge(Person person) {
- person.setAge(25);
- }
執行完以上代碼,會打印出什麼內容呢?如果你Java基礎還可以,那麼很容易就能知道會輸出什麼內容,想要知道以上代碼會打印什麼內容,需要你明白Java代碼在stack和heap中是怎麼工作的。下面我們結合幾張圖來看看:
- int i = 1;
- Person xiaoqiang = new Person("小強", 21);
- Person xiaoming = new Person("小明", 22);
當我們執行完上面三行代碼時,內存中的情況如下圖所示:
我們知道stack是用來存放變量的,所以age、xiaoqiang和xiaoming三個變量會被存放到stack裏,而age又是int類型,所以它的值也會被存放在stack裏面。xiaoqiang和xiaoming爲Person類型的引用變量,所以stack只會存放它們的一個引用,也就是對應對象的內存地址,而它們真正的內容被存放在了heap裏面。
當執行到testReference.selfPlus(i);時,selfPlus(int i)方法被調用,此時會在stack中爲形參I開闢一塊內存空間,並將其值設置爲1,此時內存中的情況如下:
因爲調用selfPlus(int i)方法時,將age作爲形參傳遞給該方法,相當於將age的值複製一份給i,所以現在i的值爲1,接着執行i = i + 1;此時i的值被修改爲2,如圖:
此時被修改的只是age的副本,而並非age本身,所以age仍爲1,當selfPlus(int i)方法被執行完,i被銷燬,age不變。接下來看xiaoqiang,當調用changeName(Person person)方法時,會在stack中爲person分配一塊空間,裏面存放的是xiaoqiang指向的地址,如圖:
然後執行到person = new Person("小剛");時,由於又new了一個Person對象,所以在堆中會新建一個person,姓名叫小剛,並且會將person執行小剛的地址,如圖:
此時,person指向的對象由小強變成了小剛,但是xiaoqiang所指向的對象仍然是小強,並沒有發生任何變化。當changeName方法執行完以後,person被銷燬,而小剛也會因爲沒有任何對象對其進行引用,隨後被垃圾回收器回收掉。
下面到了最後一個方法了,當執行testReference.changeAge(xiaoming);時,調用changeAge(Person person)方法,同樣會在stack中爲person分配一塊空間,這次裏面存放的是xiaoming對應的內存地址,如圖:
然後執行person.setAge(25);,此時person指向的對象爲小明,所以在執行setAge方法時,修改的就是heap中小明的屬性值,此時小明的年齡被修改爲25,。方法執行完畢,person被銷燬,內存中最終結果如下:
內存中的最終情況就如上圖所示,當然當main方法執行完以後,之前創建的所有對象都會被銷燬。OK,每天上班做項目的你是不是把一些基礎的東西忘了呢?如果是的話就趕快來補一補吧,好處還是很多的。
【本文轉至】:http://blog.csdn.net/liushuijinger/article/details/41605387