您的位置:首頁>正文

Java中棧(stack)和堆(heap)附實例詳解

程式設計是一種單調的生活, 因此程式師比普通人需要更多的關懷, 更多的友情。 喜歡右上角請 關注, 謝謝!

前言

按照編譯原理的觀點,程式運行時的記憶體分配有三種策略,分別是靜態的,棧式的,和堆式的.

靜態存儲分配要求在編譯時能知道所有變數的存儲要求,

棧式存儲分配要求在過程的入口處必須知道所有的存儲要求,

堆式存儲分配則專門負責在編譯時或運行時模組入口處都無法確定存儲要求的資料結構的記憶體分配,比如可變長度串和物件實例.

概念

堆主要用來存放對象的, 棧主要是用來執行程式的

棧記憶體:當定義一個變數或物件的引用變數時,Java就在棧中為這個變數分配記憶體空間,當超過變數的作用域後, Java會自動釋放掉為該變數所分配的記憶體空間, 該記憶體空間可以立即被另作他用

堆記憶體:用來存放由new創建的物件和陣列, 在堆中分配的記憶體,

由Java虛擬機器的自動垃圾回收器來管理。

注意:棧與堆都是Java用來在Ram中存放資料的地方。 與C++不同, Java自動管理棧和堆, 程式師不能直接地設置棧或堆。

優缺點比較:

棧的優點:存取速度比堆要快, 僅次於寄存器, 棧資料可以共用。 例如int a = 3; int b = 3;

編譯器先處理int a = 3;首先它會在棧中創建一個變數為a的引用, 然後查找棧中是否有3這個值, 如果沒找到, 就將3存放進來, 然後將a指向3。 接著處理int b = 3;在創建完b的引用變數後, 因為在棧中已經有3這個值, 便將b直接指向3。 這樣, 就出現了a與b同時均指向3的情況。 這時, 如果再令a=4;那麼編譯器會重新搜索棧中是否有4值, 如果沒有, 則將4存放進來, 並令a指向4;如果已經有了, 則直接將a指向這個地址。

因此a值的改變不會影響到b的值。

注意:這種資料的共用與兩個物件的引用同時指向一個物件的這種共用是不同的, 因為這種情況a的修改並不會影響到b, 它是由編譯器完成的, 它有利於節省空間。 而一個物件引用變數修改了這個物件的內部狀態, 會影響到另一個物件引用變數

棧的缺點:

存在棧中的資料大小與生存期必須是確定的, 缺乏靈活性。

棧中主要存放一些基本類型的變數(,int, short, long, byte, float, double, boolean, char)和對象控制碼。

String是一個特殊的包裝類資料。 可以用:

String str = new String("abc");

String str = "abc";

兩種的形式來創建, 第一種是用new()來新建對象的, 它會在存放於堆中。 每調用一次就會創建一個新的物件。

而第二種是先在棧中創建一個對String類的物件引用變數str, 然後查找棧中有沒有存放"abc",

如果沒有, 則將"abc"存放進棧, 並令str指向”abc”, 如果已經有”abc” 則直接令str指向“abc”。

因此:

情況一:

String str1 = "abc"; String str2 = "abc";

System.out.println(str1==str2); //true

情況二:

String str1 =new String("abc"); String str2 =new String("abc");

System.out.println(str1==str2); //false

情況三:

String s1 = "ja"; String s2 = "va";

String s3 = "java"; String s4 = s1 + s2;

System.out.println(s3 == s4);//false

System.out.println(s3.equals(s4));//true

不同維度的區別總結

1.空間分配區別:

棧(作業系統):由作業系統自動分配釋放 , 存放函數的參數值, 區域變數的值等。 其操作方式類似於資料結構中的棧;

堆(作業系統): 一般由程式師分配釋放, 若程式師不釋放, 程式結束時可能由OS回收, 分配方式倒是類似於鏈表。

2.堆疊緩存方式區別:

棧使用的是一級緩存, 他們通常都是被調用時處於存儲空間中, 調用完畢立即釋放;

堆是存放在二級緩存中, 生命週期由虛擬機器的垃圾回收演算法來決定(並不是一旦成為孤兒對象就能被回收)。 所以調用這些物件的速度要相對來得低一些。

3.堆疊資料結構區別:

堆(資料結構):先進先出, 如 樹

棧(資料結構):一種先進後出的資料結構。 如 桶

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示