1.數據類型
Java虛擬機中,數據類型能夠分爲兩類:基本類型和引用類型。基本類型的變量保存原始值,即:他表明的值就是數值自己;而引用類型的變量保存引用值。「引用值」表明了某個對象的引用,而不是對象自己,對象自己存放在這個引用值所表示的地址的位置。java
2.堆與棧數組
堆和棧是程序運行的關鍵,棧是運行時的單位,而堆是存儲的單位。棧解決程序的運行問題,即程序如何執行,或者說如何處理數據;堆解決的是數據存儲的問題,即數據怎麼放、放在哪兒。緩存
在Java中一個線程就會相應有一個線程棧與之對應,這點很容易理解,由於不一樣的線程執行邏輯有所不一樣,所以須要一個獨立的線程棧。而堆則是全部線程共享的。棧由於是運行單位,所以裏面存儲的信息都是跟當前線程(或程序)相關信息的。包括局部變量、程序運行狀態、方法返回值等等;而堆只負責存儲對象信息。數據結構
3.爲何要把堆和棧區分出來呢?棧中不是也能夠存儲數據嗎?模塊化
第一,從軟件設計的角度看,棧表明了處理邏輯,而堆表明了數據。這樣分開,使得處理邏輯更爲清晰。分而治之的思想。這種隔離、模塊化的思想在軟件設計的方方面面都有體現。
第二,堆與棧的分離,使得堆中的內容能夠被多個棧共享(也能夠理解爲多個線程訪問同一個對象)。這種共享的收益是不少的。一方面這種共享提供了一種有效的數據交互方式(如:共享內存),另外一方面,堆中的共享常量和緩存能夠被全部棧訪問,節省了空間。
第三,棧由於運行時的須要,好比保存系統運行的上下文,須要進行地址段的劃分。因爲棧只能向上增加,所以就會限制住棧存儲內容的能力。而堆不一樣,堆中的對象是能夠根據須要動態增加的,所以棧和堆的拆分,使得動態增加成爲可能,相應棧中只需記錄堆中的一個地址便可。
第四,面向對象就是堆和棧的完美結合。其實,面向對象方式的程序與之前結構化的程序在執行上沒有任何區別。可是,面向對象的引入,使得對待問題的思考方式發生了改變,而更接近於天然方式的思考。當咱們把對象拆開,你會發現,對象的屬性其實就是數據,存放在堆中;而對象的行爲(方法),就是運行邏輯,放在棧中。咱們在編寫對象的時候,其實即編寫了數據結構,也編寫的處理數據的邏輯。不得不認可,面向對象的設計,確實很美。函數
在Java中,Main函數就是棧的起始點,也是程序的起始點。spa
程序要運行老是有一個起點的。同C語言同樣,java中的Main就是那個起點。不管什麼java程序,找到main就找到了程序執行的入口:)線程
4.堆中存什麼?棧中存什麼?設計
堆中存的是對象。棧中存的是基本數據類型和堆中對象的引用。一個對象的大小是不可估計的,或者說是能夠動態變化的,可是在棧中,一個對象只對應了一個4btye的引用(堆棧分離的好處:))。指針
爲何不把基本類型放堆中呢?由於其佔用的空間通常是1~8個字節——須要空間比較少,並且由於是基本類型,因此不會出現動態增加的狀況——長度固定,所以棧中存儲就夠了,若是把他存在堆中是沒有什麼意義的(還會浪費空間,後面說明)。能夠這麼說,基本類型和對象的引用都是存放在棧中,並且都是幾個字節的一個數,所以在程序運行時,他們的處理方式是統一的。可是基本類型、對象引用和對象自己就有所區別了,由於一個是棧中的數據一個是堆中的數據。最多見的一個問題就是,Java中參數傳遞時的問題。
要說明這個問題,先要明確兩點:
1. 不要試圖與C進行類比,Java中沒有指針的概念
2. 程序運行永遠都是在棧中進行的,於是參數傳遞時,只存在傳遞基本類型和對象引用的問題。不會直接傳對象自己。
明確以上兩點後。Java在方法調用傳遞參數時,由於沒有指針,因此它都是進行傳值調用(這點能夠參考C的傳值調用)。所以,不少書裏面都說Java是進行傳值調用,這點沒有問題,並且也簡化的C中複雜性。
可是傳引用的錯覺是如何形成的呢?在運行棧中,基本類型和引用的處理是同樣的,都是傳值,因此,若是是傳引用的方法調用,也同時能夠理解爲「傳引用值」的傳值調用,即引用的處理跟基本類型是徹底同樣的。可是當進入被調用方法時,被傳遞的這個引用的值,被程序解釋(或者查找)到堆中的對象,這個時候纔對應到真正的對象。若是此時進行修改,修改的是引用對應的對象,而不是引用自己,即:修改的是堆中的數據。因此這個修改是能夠保持的了。
對象,從某種意義上說,是由基本類型組成的。能夠把一個對象看做爲一棵樹,對象的屬性若是仍是對象,則仍是一顆樹(即非葉子節點),基本類型則爲樹的葉子節點。程序參數傳遞時,被傳遞的值自己都是不能進行修改的,可是,若是這個值是一個非葉子節點(即一個對象引用),則能夠修改這個節點下面的全部內容。
堆和棧中,棧是程序運行最根本的東西。程序運行能夠沒有堆,可是不能沒有棧。而堆是爲棧進行數據存儲服務,說白了堆就是一塊共享的內存。不過,正是由於堆和棧的分離的思想,才使得Java的垃圾回收成爲可能。
Java中,棧的大小經過-Xss來設置,當棧中存儲數據比較多時,須要適當調大這個值,不然會出現java.lang.StackOverflowError異常。常見的出現這個異常的是沒法返回的遞歸,由於此時棧中保存的信息都是方法返回的記錄點。