今天在和同事討論的時候談到了關於static的問題,正巧自己有一些忘記了,就特來學習一番。
首先,Java中的static關鍵字主要用於內存管理。static 關鍵字屬於類,而不是類的示例。(敲黑板)。在程序中任何變量或者代碼都是編譯時分配代碼的,而靜態修飾的就會一直存在內存中,直到程序退出。也就是說,在我們的日常使用中,如果在某個類中要使用其他類,那麼只能先把待使用的類進行實例化,然後通過對象引用它,但是,如果有static修飾的成員,那麼我們是可以 類名.成員名 來直接進行訪問的,所以這裏也就說明了上面的那句話:static 關鍵字屬於類,而不是類的示例。
static 關鍵字可以修飾的如下:
- 變量
- 方法
- 塊(也就是局部代碼塊)
- 內部類
Java 修飾靜態變量
被static修飾的變量成爲靜態變量,被JVM加載時只被加載一次到內存中,所以節省了內存(當然有併發情況就要考慮的複雜了)
比如,我們現在有個people類,如果現在有100個人,那麼我們就要初始化100個實例,如果這個類中含有如下字段
private static String type = "學生";
那麼對是學生的人羣,這個字段只需要初始化一次就夠,其他人的引用都指向同一個內存,節約了內存。
Java 修飾靜態方法
被static修飾的方法稱爲靜態方法,其中,靜態方法屬於類而不是屬於對象(繼續敲黑板),所以無需實例化就可以調用靜態方法。因此不能使用 this 和 supper 進行調用,這裏要注意下,而且static 獨立於示例,所以是不能修飾 抽象的 abstract 的。
Java 修飾代碼塊
- 用於初始化靜態數據成員。
- 在類加載時,在main方法前執行。
- 可以有多個靜態代碼塊。在存在多個時,JVMM會按照它們出現的先後順序執行,每個代碼塊只會執行一次
public class StaticTest { static { System.out.println("這是一個static 塊 ------- 1"); } static { System.out.println("這是一個static 塊 ------- 2"); } public static void main(String[] args) { System.out.println("這是一個main方法"); } }
輸出是:
這是一個static 塊 ------- 1 這是一個static 塊 ------- 2 這是一個main方法
我們在使用static的時候,會經常搭配final一起使用,static final 修飾變量,表示不可修改;修飾方法,表示不可被覆蓋。
但是,我們在使用的時候,不可修改指的是實例常量,實例本身是不可以改變了,比如我們把這個實例變成 null,這個時候就會編譯出錯。
但是我們可以改變實例對象中的屬性的,比如
static 修飾內部類
在一個類中創建另一個類,叫做內部類,用static 修飾內部類,叫做靜態內部類,當然,內部類也可以是非靜態的。
使用場景:創建內部類時,不想創建一次內部類就需要創建一次外圍類。內部類與外部類有很強聯繫,增加可讀性。
我們知道,非靜態內部類在編譯完成後,會保存着一個指向外部類的引用,But ,靜態內部類是沒有的,它的創建是不需要依賴外部類的,但是它不能使用任何外圍類的非靜態成員變量和方法。
靜態變量、靜態塊和靜態方法的區別
- 靜態代碼塊是自動執行的
- 靜態方法是被調用才執行的
- 靜態代碼塊和靜態變量的執行順序也是按順序執行的。比如
private static int num = 10; static { num = 20; } public static void main(String[] args) { System.out.println(num); }
輸出
20
當然,如果是下面這樣的話,其實
System.out.println(num); 輸出的還是 private static int num = 10;定義的內容
private static int num = 10; static { int num = 20;//變成了局部變量 } public static void main(String[] args) { System.out.println(num); }