1. 程式人生 > >Java中的基礎----堆與棧的介紹、區別

Java中的基礎----堆與棧的介紹、區別

堆和棧都是Java中常用的儲存結構,都是記憶體中存放資料的地方。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~我是可愛的分割線~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

堆:(物件)

引用型別的變數,其記憶體分配在堆上或者常量池(字串常量、基本資料型別常量),需要通過new等方式來建立。

堆記憶體主要作用是存放執行時建立(new)的物件。

(主要用於存放物件,存取速度慢,可以執行時動態分配記憶體,生存期不需要提前確定)

棧:(基本資料型別變數、物件的引用變數)

基本資料型別的變數(int、short、long、byte、float、double、boolean、char等)以及物件的引用變數,其記憶體分配在棧上,變量出了作用域就會自動釋放。

棧記憶體的主要作用是存放基本資料型別和引用變數。棧的記憶體管理是通過棧的"後進先出"模式來實現的。

(主要用來執行程式,存取速度快,大小和生存期必須確定,缺乏靈活性)

class 鴨子{     
    private int age;
    private int weight;
    public 鴨子(int age,int weight){
         this.age=age;
         this.weight=weight;
    }
}

public class Test{
    public static void main(String[] args){
        //int i=0;      //基本資料型別變數
        鴨子 duck =new 鴨子(1,1000);   //duck是物件的引用變數,存在棧;鴨子(1,1000)是實際的物件,存在堆。
    }
}

圖例如下:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~我是可愛的分割線~~~~~~~~~~~~~

PS:

JVM:

是基於堆疊的虛擬機器,每個Java程式在一個獨立的JVM例項上執行,每個JVM例項對應一個堆,

同個java程式內的多執行緒執行在同個JVM例項上,多個執行緒之間共享堆記憶體(多線訪問堆時,要實現資料的同步)。

----------------------------------------------------------------------------------wo ye shi ke ai de fen ge xian-------------------------------------------------------

為什麼又棧記憶體和堆記憶體之分?

當一個方法執行時,每個方法都會建立自己的記憶體棧,在這個方法定義的變數將會放到這塊棧記憶體裡,隨著方法的結束,這個方法的記憶體棧也將自動銷燬。(不需要GC回收)

因此,所有在方法中定義的區域性變數放在棧記憶體中;

當我們在程式中建立一個物件時,這個物件會被儲存到執行時資料區中,以便反覆利用(複用,因為建立物件的成本通常較大),這個執行時資料區就是堆記憶體。堆記憶體中的物件不會隨著方法的結束而銷燬,即使方法結束後,這個物件還可能被另外一個引用變數所引用(在方法的引數傳遞時很常見),則這個物件依然不會被銷燬。只有當一個物件沒有任何引用變數去引用它時,系統的垃圾回收器(GC)才會在合適的時候回收它。

為什麼上面說建立物件的開銷(成本)比較大?

來看看如何建立物件、建立物件的過程:

建立物件的根本途徑是構造器,通過new關鍵字來呼叫某個類的構造器即可建立這個類的例項。但物件不是完全由構造器來負責建立的,實際上,當程式設計師呼叫構造器時,系統會先為該物件分配記憶體空間,併為這個物件執行預設初始化,這個物件已經產生了---這些是在構造器執行之前就完成的,也就是說,當系統開始執行構造器的執行體之前,系統已經建立了一個物件,只是這物件還不能被外部程式訪問,只能在構造器中通過this來引用。當構造器的執行體執行結束後,這個物件作為構造器的返回值被返回,通常還會賦給另外一個引用型別的變數,從而讓外部程式可以訪問。(當然可以通過設定構造器的訪問許可權private,阻止其他類建立該類的例項)