理解 static (深刻了解JAVA虛擬機)

談談我對static的理解

 

由於我發現不少同窗學到這裏都會很困惑 很難理解static究竟是個什麼 

首先 static是個修飾符 被static修飾的變量咱們統稱爲靜態變量也叫類變量(爲何叫類變量呢 ?由於咱們能夠直接使用類來調用被static修飾的變量)

static 不能夠修飾局部變量!牢記 

再和你們說一下另外一種變量 也一樣是成員變量 可是沒有被static修飾 咱們叫它全局變量也是不少人嘴裏的動態變量(c中的叫法) 我有個比較更容易的記法 我叫它實例變量 即非靜態變量

(對象是類實例化來的你們確定不陌生 而非static變量想要調用的時候須要用對象(點) 因此我稱之爲實例變量)

對於靜態變量在內存中只有一個拷貝!JVM只會在加載類時爲靜態分配一次內存 靜態變量是能夠經過對象來訪問的

對於非靜態變量!你每new一個實例 JVM中就會爲你分配一次內存 實例變量能夠在內存中有多個拷貝 不影響彼此(靈活性)

static變量在RAM ROM中的存儲 存儲在數據存儲區和堆 棧 不是一個存儲區

插一嘴 講下堆和棧 

下面的聽不懂的同窗能夠先不看!

 

stack 空間小 速度比較快  用來放對象的引用
heap 大 通常全部建立的對象都放在這裏 

棧(stack):是一個先進後出的數據結構 一般用於保存方法(c:函數)中的參數 局部變量八種基本類型和自定義對象的引用(c:指針)被執行的方法也會到棧中 執行完會出棧

在java中 全部基本類型和引用類型都在棧中存儲 棧中數據的生存空間通常在當前scopes內(就是由{...}括起來的區域) 

堆(heap):是一個可動態申請的內存空間(其記錄空閒內存空間的鏈表由操做系統維護),C中的malloc語句所產生的內存空間就在堆中.

在java中,全部使用new xxx()構造出來的對象都在堆中存儲,當垃圾回收器檢測到某對象未被引用,則自動銷燬該對象.因此,理論上說

java中對象的生存空間是沒有限制的,只要有引用類型指向它,則它就能夠在任意地方被使用.

1. 棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不一樣,Java自動管理棧和堆,程序員不能直接地設置棧或堆。


2. 棧的優點是,存取速度比堆要快,僅次於直接位於CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是肯定的,缺少靈活性。另外,棧數據能夠共享。

堆的優點是能夠動態地分配內存大小,生存期也沒必要事先告訴編譯器,Java的垃圾收集器會自動收走這些再也不使用的數據。但缺點是,因爲要在運行時動態分配內存,存取速度較慢。

3. Java中的數據類型有兩種。

一種是基本類型(primitive types), 共有8種,即int, short, long, byte, float, double, boolean, char(注意,並無string的基本類型)。

這種類型的定義是經過諸如int a = 3; long b = 255L;的形式來定義的,稱爲自動變量。值得注意的是,自動變量存的是字面值,不是類的實例,即不是類的引用,這裏並無類的存在。

如int a = 3; 這裏的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數據,因爲大小可知,生存期可知(這些字面值固定定義在某個程序塊裏面,程序塊退出後,字段值就消失了),

出於追求速度的緣由,就存在於棧中。

另外,棧有一個很重要的特殊性,就是存在棧中的數據能夠共享。假設咱們同時定義:

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與b的值後,再令a=4;

那麼,b不會等於4,仍是等於3。在編譯器內部,遇到a=4;時,它就會從新搜索棧中是否有4的字面值,若是沒有,從新開闢地址存放4的值;若是已經有了,則直接將a指向這個地址。

所以a值的改變不會影響到b的值。

另外一種是包裝類數據,如Integer, String, Double等將相應的基本數據類型包裝起來的類。這些類數據所有存在於堆中,Java用new()語句來顯示地告訴編譯器,在運行時才根據須要動態建立,所以比較靈活,但缺點是

要佔用更多的時間。

4.String是一個特殊的包裝類數據。便可以用String str = new String("abc");的形式來建立,也能夠用String str = "abc";的形式來建立(做爲對比,

如今回到咱們講的static

 static修飾的變量講完了 下面講下static修飾的方法  

靜態方法有什麼好處呢 靜態方法不須要類實例化對象 就能夠直接調用

在堆和棧裏面咱們說過 對象是個佔用內存相對比較多的東西

也就是說被static修飾過的方法 再也不歸對象全部 而是屬於類 固然對象.仍是能夠調用 這在我看來是不合理的!不推薦使用 推薦直接使用類名調用 若是你看見了一個經過類名直接調用的方法或變量 那麼他必定是static的

和你們說下static的弊端 static會從你JVM加載類開始 就一直存在 直到整個程序結束纔會釋放!因此請慎用 ! 

static我我的喜歡把他做爲工具來使用 由於不須要new對象就能夠直接用了 例如咱們之後要鏈接數據庫 就可使用static修飾的方法 由於鏈接數據庫並非某一個對象所特有的 他只是一個工具

最後給你們講個static修飾的代碼塊

靜態代碼塊和靜態方法的區別在於

靜態代碼塊是自動執行的 而方法是你調用他的時候纔會執行

靜態方法只能直接調用本類中其餘的靜態成員(變量 方法) 靜態沒法調用非靜態(先上車後上車)在JVM中被static修飾的會被首先被載入 而這個時候其餘未被static修飾的尚未載入 因此是調用不到的

行了 累了= =不寫了 本身多理解 不會的抽時間問我吧

下面給大家附上一幅JVM3個我講到的存儲區=。=本身理解  

相關文章
相關標籤/搜索