你就簡(jiǎn)單的來(lái)理解就可以了 堆棧就是兩種存放數據的方式
不要new直接來(lái)定義的是棧 用new來(lái)定義的就是堆
首先來(lái)講解棧 棧的優(yōu)勢是,存取速度比堆要快。但缺點(diǎn)是缺乏靈活性
而堆測試速度慢 但是靈活性好
比如八大基本數據類(lèi)型 在你int sum = 0;的時(shí)候 就是sum是一個(gè)指向int類(lèi)型的引用,指向0這個(gè)字面值
你在頂一個(gè) int i=0;他會(huì )去找有沒(méi)有0 有的話(huà)就會(huì )指向它 所以棧具有共享數據的特性
而當你String str = new String("a");的時(shí)候 它就會(huì )在堆中建立一個(gè)對象
其實(shí)你就理解成兩種方式的存放數據的方式就行
簡(jiǎn)單的說(shuō) 其實(shí) 棧 就是存放變量引用的一個(gè)地方, 堆 就是存放實(shí)際對象的地方 也就是.
比如: int i = 7; 這個(gè) 其實(shí)是存在棧里邊的。內容為 i = 7。
Apple app = new Apple(); 這個(gè) app 是在棧里邊的 他對應的是一個(gè)內存地址也在堆里邊, 而這個(gè)內存地址對應的是堆里邊存放 Apple 實(shí)例的地址。
String s = "Hello World!"; 這個(gè)其實(shí)是存在另外一塊靜態(tài)代碼區。
總體來(lái)說(shuō): 棧--主要存放引用 和基本數據類(lèi)型。
堆--用來(lái)存放 new 出來(lái)的對象實(shí)例。
Java中堆棧的概念是邏輯上的,在完全符合Java規范的Java處理器面世之前,所有Java虛擬機提供的內容都是由軟件模擬出來(lái)的。
什么叫堆?你用十幾個(gè)麻將牌豎直疊成一摞這叫堆,你可以從上面、下面、中間任意抽出一張牌,也可以任意插入一張。
什么叫棧?AK-47的彈匣就是一個(gè)棧,在上面的子彈沒(méi)被取出之前,你無(wú)法取出下面的子彈——盡管你可以從邊上的透明部分讀出里面裝的是什么型號、顏色的子彈。
堆很靈活,但是不安全。對于對象,我們要動(dòng)態(tài)地創(chuàng )建、銷(xiāo)毀,不能說(shuō)后創(chuàng )建的對象沒(méi)有銷(xiāo)毀,先前創(chuàng )建的對象就不能銷(xiāo)毀,那樣的話(huà)我們的程序就寸步難行,所以Java中用堆來(lái)存儲對象。而一旦堆中的對象被銷(xiāo)毀,我們繼續引用這個(gè)對象的話(huà),就會(huì )出現著(zhù)名的 NullPointerException,這就是堆的缺點(diǎn)——錯誤的引用邏輯只有在運行時(shí)才會(huì )被發(fā)現。
棧不靈活,但是很?chē)栏瘢前踩模子诠芾怼R驗橹灰厦娴囊脹](méi)有銷(xiāo)毀,下面引用就一定還在,所以,在棧中,上面引用永遠可以通過(guò)下面引用來(lái)查找對象,同時(shí)如果確認某一區間的內容會(huì )一起存在、一起銷(xiāo)毀,也可以上下互相引用。在大部分程序中,都是先定義的變量、引用先進(jìn)棧,后定義的后進(jìn)棧,同時(shí),區塊內部的變量、引用在進(jìn)入區塊時(shí)壓棧,區塊結束時(shí)出棧,理解了這種機制,我們就可以很方便地理解各種編程語(yǔ)言的作用域的概念了,同時(shí)這也是棧的優(yōu)點(diǎn)——錯誤的引用邏輯在編譯時(shí)就可以被發(fā)現。
在Java中,引用可以理解為一個(gè)永遠指向對象的指針,Java沒(méi)有指向指針的指針。
關(guān)于堆棧的資料幾乎每個(gè)講數據結構的書(shū)上都有,而至于Java中堆、棧的具體機制你可以參考一些關(guān)于Java虛擬機原理的書(shū),不過(guò)這個(gè)好像比較難理解,我是沒(méi)指望理解的了。
以上都是我的個(gè)人觀(guān)點(diǎn),僅供參考。
內存中的兩種存儲區
1..棧的特點(diǎn)是 容量小 速度快 適合存放小型數據 如基本數據類(lèi)型和對象類(lèi)型的引用
在棧中變量直接指向存放變量值的空間 對于對象引用則存放對象在堆中的內存地址
2..堆的特點(diǎn)和棧相反 因此適合存放對象本身
3..對象引用訪(fǎng)問(wèn)對象的原理是 先通過(guò)該引用找到棧中的數據 即對象的地址 在通過(guò)該
地址訪(fǎng)問(wèn)對象 這就是為什么 對象 a=null; 調用a.方法(屬性) 會(huì )引發(fā)異常 因為找不到
實(shí)際對象的地址 向一個(gè)不存在的對象發(fā)送消息 如同叫一個(gè)不存在的人去幫你做事
程序不崩潰才怪
簡(jiǎn)單的說(shuō):Java把內存劃分成兩種:一種是棧內存,一種是堆內存。
在函數中定義的一些基本類(lèi)型的變量和對象的引用變量都在函數的棧內存中分配。當在一段代碼塊定義一個(gè)變量時(shí),Java就在棧中為這個(gè)變量分配內存空間,當超過(guò)變量的作用域后,Java會(huì )自動(dòng)釋放掉為該變量所分配的內存空間,該內存空間可以立即被另作他用。
堆內存用來(lái)存放由new創(chuàng )建的對象和數組。在堆中分配的內存,由Java虛擬機的自動(dòng)垃圾回收器來(lái)管理。在堆中產(chǎn)生了一個(gè)數組或對象后,還可以在棧中定義一個(gè)特殊的變量,讓棧中這個(gè)變量的取值等于數組或對象在堆內存中的首地址,棧中的這個(gè)變量就成了數組或對象的引用變量。引用變量就相當于是為數組或對象起的一個(gè)名稱(chēng),以后就可以在程序中使用棧中的引用變量來(lái)訪(fǎng)問(wèn)堆中的數組或對象
堆棧是一種執行“后進(jìn)先出”算法的數據結構。
設想有一個(gè)直徑不大、一端開(kāi)口一端封閉的竹筒。有若干個(gè)寫(xiě)有編號的小球,小球的直徑比竹筒的直徑略小。現在把不同編號的小球放到竹筒里面,可以發(fā)現一種規律:先放進(jìn)去的小球只能后拿出來(lái),反之,后放進(jìn)去的小球能夠先拿出來(lái)。所以“先進(jìn)后出”就是這種結構的特點(diǎn)。
堆棧就是這樣一種數據結構。它是在內存中開(kāi)辟一個(gè)存儲區域,數據一個(gè)一個(gè)順序地存入(也就是“壓入——push”)這個(gè)區域之中。有一個(gè)地址指針總指向最后一個(gè)壓入堆棧的數據所在的數據單元,存放這個(gè)地址指針的寄存器就叫做堆棧指示器。開(kāi)始放入數據的單元叫做“棧底”。數據一個(gè)一個(gè)地存入,這個(gè)過(guò)程叫做“壓棧”。在壓棧的過(guò)程中,每有一個(gè)數據壓入堆棧,就放在和前一個(gè)單元相連的后面一個(gè)單元中,堆棧指示器中的地址自動(dòng)加1。讀取這些數據時(shí),按照堆棧指示器中的地址讀取數據,堆棧指示器中的地址數自動(dòng)減 1。這個(gè)過(guò)程叫做“彈出pop”。如此就實(shí)現了后進(jìn)先出的原則。
堆棧是計算機中最常用的一種數據結構,比如函數的調用在計算機中是用堆棧實(shí)現的。
堆棧可以用數組存儲,也可以用以后會(huì )介紹的鏈表存儲。
下面是一個(gè)堆棧的結構體定義,包括一個(gè)棧頂指針,一個(gè)數據項數組。棧頂指針最開(kāi)始指向-1,然后存入數據時(shí),棧頂指針加1,取出數據后,棧頂指針減1。
#define MAX_SIZE 100
typedef int DATA_TYPE;
struct stack
{
DATA_TYPE data[MAX_SIZE];
int top;
};
在C++中,內存分成5個(gè)區,他們分別是堆、棧、自由存儲區、全局/靜態(tài)存儲區和常量存儲區。
棧,就是那些由編譯器在需要的時(shí)候分配,在不需要的時(shí)候自動(dòng)清楚的變量的存儲區。里面的變量通常是局部變量、函數參數等。
堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個(gè)new就要對應一個(gè)delete。如果程序員沒(méi)有釋放掉,那么在程序結束后,操作系統會(huì )自動(dòng)回收。
自由存儲區,就是那些由malloc等分配的內存塊,他和堆是十分相似的,不過(guò)它是用free來(lái)結束自己的生命的。
全局/靜態(tài)存儲區,全局變量和靜態(tài)變量被分配到同一塊內存中,在以前的C語(yǔ)言中,全局變量又分為初始化的和未初始化的,在C++里面沒(méi)有這個(gè)區分了,他們共同占用同一塊內存區。
常量存儲區,這是一塊比較特殊的存儲區,他們里面存放的是常量,不允許修改(當然,你要通過(guò)非正當手段也可以修改,而且方法很多.
聲明:本網(wǎng)站尊重并保護知識產(chǎn)權,根據《信息網(wǎng)絡(luò )傳播權保護條例》,如果我們轉載的作品侵犯了您的權利,請在一個(gè)月內通知我們,我們會(huì )及時(shí)刪除。
蜀ICP備2020033479號-4 Copyright ? 2016 學(xué)習?shū)B(niǎo). 頁(yè)面生成時(shí)間:2.943秒