談談我對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個我講到的存儲區=。=自己理解