Java中的棧和堆
JAVA在程序運行時,在內存中劃分5片空間進行數據的存儲。分別是:1:寄存器。2:本地方法區。3:方法區。4:棧。5:堆。
基本,棧stack和堆heap這兩個概念很重要,不了解清楚,後面就不用學了。
以下是這幾天棧和堆的學習記錄和心得。得些記錄下來。以後有學到新的,會慢慢補充。
一、先說一下最基本的要點
基本數據類型、局部變量都是存放在棧內存中的,用完就消失。
new創建的實例化對象及數組,是存放在堆內存中的,用完之後靠垃圾回收機制不定期自動消除。
二、先明確以上兩點,以下示例就比較好理解了
示例1
main()
int x=1;
show ()
int x=2
主函數main()中定義變量int x=1,show()函數中定義變量int x=1。最後show()函數執行完畢。
以上程序執行步驟:
第1步——main()函數是程序入口,JVM先執行,在棧內存中開辟一個空間,存放int類型變量x,同時附值1。
第2步——JVM執行show()函數,在棧內存中又開辟一個新的空間,存放int類型變量x,同時附值2。
此時main空間與show空間並存,同時運行,互不影響。
第3步——show()執行完畢,變量x立即釋放,空間消失。但是main()函數空間仍存在,main中的變量x仍然存在,不受影響。
示意圖如下:
——————————————————————————————————————————————————————————————————————
示例2
main()
int[] x=new int[3];
x[0]=20
主函數main()中定義數組x,元素類型int,元素個數3。
以上程序執行步驟
第1步——執行int[] x=new int[3];
隱藏以下幾分支
JVM執行main()函數,在棧內存中開辟一個空間,存放x變量(x變量是局部變量)。
同時,在堆內存中也開辟一個空間,存放new int[3]數組,堆內存會自動內存首地址值,如0x0045。
數組在棧內存中的地址值,會附給x,這樣x也有地址值。所以,x就指向(引用)了這個數組。此時,所有元素均未附值,但都有默認初始化值0。
第2步——執行x[0]=20
即在堆內存中將20附給[0]這個數組元素。這樣,數組的三個元素值分別為20,0,0
示圖如下:
——————————————————————————————————————————————————————————————————————
示例3
main()
int[] x=new int[3];
x[0]=20
x=null;
以上步驟執行步驟
第1、2步——與示例2完全一樣,略。
第3步——執行x=null;
null表示空值,即x的引用數組內存地址0x0045被刪除了,則不再指向棧內存中的數組。此時,堆中的數組不再被x使用了,即被視為垃圾,JVM會啟動垃圾回收機制,不定時自動刪除。
示圖如下
——————————————————————————————————————————————————————————————————
示例4
main()
int[] x=new int[3];
int[] y=x;
y[1]=100
x=null;
以上步驟執行步驟
第1步——與示例2第1步一致,略。
第2步——執行int[] y=x,
在棧內存定義了新的數組變量內存y,同時將x的值0x0045附給了y。所以,y也指向了堆內存中的同一個數組。
第3步——執行y[1]=100
即在堆內存中將20附給[0]這個數組元素。這樣,數組的三個元素值分別為0,100,0
第4步——執行x=null
則變量x不再指向棧內存中的數組了。但是,變量y仍然指向,所以數組不消失。
示圖如下
——————————————————————————————————————————————————————————————————
示例5
Car c=new Car;
c.color="blue";
Car c1=new Car;
c1.num=5;
雖然是個對象都引用new Car,但是是兩個不同的對象。每一次new,都產生不同的實體
——————————————————————————————————————————————————————————————————
示例6
Car c=new Car;
c.num=5;
Car c1=c;
c1.color="green";
c.run();
Car c1=c,這句話相當於將對象復制一份出來,兩個對象的內存地址值一樣。所以指向同一個實體,對c1的屬性修改,相當於c的屬性也改了。
三、棧和堆的特點
棧:
函數中定義的基本類型變量,對象的引用變量都在函數的棧內存中分配。
棧內存特點,數數據一執行完畢,變量會立即釋放,節約內存空間。
棧內存中的數據,沒有默認初始化值,需要手動設置。
堆:
堆內存用來存放new創建的對象和數組。
堆內存中所有的實體都有內存地址值。
堆內存中的實體是用來封裝數據的,這些數據都有默認初始化值。
堆內存中的實體不再被指向時,JVM啟動垃圾回收機制,自動清除,這也是JAVA優於C++的表現之一(C++中需要程序員手動清除)。
註:
什麽是局部變量:定義在函數中的變量、定義在函數中的參數上的變量、定義在for循環內部的變量
Java中的棧和堆