首先咱們來講說內存,由於從內存的角度來出發來分析一些變量,引用或者對象的生命週期會更好理解一些。java
java是一門編程語言,他跟C++有什麼不一樣呢?本質上,他們都是同樣的,異曲同工。由於底層都是操做內存和磁盤的工具,只是語法不一樣,表現形式不一樣而已。程序員
因此有的時候沒必要刨根問底,由於這可能只是語言的一種規則而已。編程
java中都是以對象和對象的引用形式來操做數據的,那麼java中是如何分配這些存儲引用和內存的呢?編程語言
1. 寄存器。這是最快的存儲區,覺得它位於不一樣於其餘存儲區的地方——處理器內部。可是寄存器的數量極其有限,因此寄存器根據需求進行分配。你不能直接控制,也不能在程序中感受到寄存器存在的任何跡象。工具
2. 棧(又名堆棧),原型就是碟盤子模型,先放的盤子後拿。棧位於通用RAM(隨機訪問存儲器)中,但經過堆棧指針能夠直接從處理器那裏得到直接支持。經過棧頂指針的上下移動來建立和釋放內存,這是一種快速有效的分配存儲的方法,僅次於寄存器。可是這種方式,java系統必須知道存儲在堆棧內全部項的生命週期,以便上下移動堆棧指針。因此對象的引用存在與堆棧中(由於由確切的生命週期),可是對象不會存於堆棧中(無確切的生命週期)。spa
3.堆。一種通用的內存池,也是位於RAM區,用於存放全部的java對象。堆不一樣與堆棧的好處是:編譯器不須要知道存儲的數據在堆裏存活多長時間。所以,在堆裏分配存儲由很大的靈活性。當須要一個對象時,只需new一個,當執行時,會自動在堆裏進行分配內存。固然,爲了這種靈活性必須付出相應的代價:用堆進行存儲分配和清理可能比用堆棧進行存儲分配須要更多的時間。(對比於C++,對象會在棧中存儲,由於對象的生命週期都是程序員本身控制的)指針
4.常量存儲。常量值一般直接存放在程序代碼的內部。對象
5.非RAM存儲。若是數據徹底存活於程序以外,那麼能夠不受程序的任何控制,在程序沒有運行時也能夠存在。其中兩個基本的例子就是流對象和持久化對象。在流對象中,對象轉化成字節流,一般被髮送給另外一臺機器。在持久化對象中,對象被存放於磁盤上,所以,即便程序終止,他們仍能夠保持本身的狀態。這種存儲方式的技巧在於:把對象轉化成爲能夠存儲在其餘媒介上的事物,在須要時,可恢復成常規的、基於RAM的對象。java提供了對輕量級持久化的支持。生命週期
java對於小的,基本的變量是這樣處理的:內存
將他們固定長度,直接存儲值於堆棧中,因此java的基本類型都是有固定取值範圍的。
java基本類型長度不變也是java的可移植性的重要緣由。
變量的生命週期每每是由大括號決定的,而對象則否則
{
String s = new String("a string");
}
在上面的這段代碼中,引用s在做用域終點就消失了。然而,s指向的String對象仍然繼續佔據着內存空間。
咱們已經沒法在做用與以外訪問這個對象,由於他惟一的引用已經失效了。
事實證實,由new建立的對象,只要你須要,就會一直保留下去。
那麼他們何時消亡,以致於不會填滿內存呢?這就引出了垃圾回收器。
垃圾回收器的做用:監視new建立的全部對象,並辨識哪些對象是不會再被引用的對象,隨後,釋放這些對象的內存空間,以便供其餘新的對象使用。因此對象不須要程序員本身回收。神奇的GC...
3、有關static
class StaticTest {
static int i = 47;
}
即便你建立了兩個StaticTest對象,StaticTest.i也只有一份存儲空間,這兩個對象共享一個i。
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
在這裏,st1.i和 st2.i指向同一存儲空間,所以他們具備相同的值47.
因此static字段對每一個類來講只有一份存儲空間,而非static字段則是對每一個對象有一個存儲空間。