1、static存在的主要意義
static的主要意義是在于創建獨立于具體對象的域變量或者方法。以致于即使沒有創建對象,也能使用屬性和調用方法!
static關鍵字還有一個比較關鍵的作用就是 用來形成靜態代碼塊以優化程序性能。static塊可以置于類中的任何地方,類中可以有多個static塊。在類初次被加載的時候,會按照static塊的順序來執行每個static塊,并且只會執行一次。
為什么說static塊可以用來優化程序性能,是因為它的特性:只會在類加載的時候執行一次。因此,很多時候會將一些只需要進行一次的初始化操作都放在static代碼塊中進行。
2、static的獨特之處
被static修飾的變量或者方法是獨立于該類的任何對象,也就是說,這些變量和方法不屬于任何一個實例對象,而是被類的實例對象所共享。
在該類被第一次加載的時候,就會去加載被static修飾的部分,而且只在類第一次使用時加載并進行初始化,注意這是第一次用就要初始化,后面根據需要是可以再次賦值的。
static變量值在類加載的時候分配空間,以后創建類對象的時候不會重新分配。賦值的話,是可以任意賦值的!
被static修飾的變量或者方法是優先于對象存在的,也就是說當一個類加載完畢之后,即便沒有創建對象,也可以去訪問。
3、static 關鍵字主要使用場景
static 關鍵字主要有四種使用場景
- 修飾成員變量和方法
- 靜態代碼塊
- 修飾類【只能修飾內部類也就是靜態內部類】
- 靜態導包
下面是詳細介紹
4、修飾成員變量和成員方法(常用)
被 static 修飾的成員屬于類,不屬于單個這個類的某個對象,被類中所有對象共享,可以并且建議通過類名調用。被static 聲明的成員變量屬于靜態成員變量,靜態變量 存放在 Java 內存區域的方法區。
方法區與 Java 堆一樣,是各個線程共享的內存區域,它用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。雖然Java虛擬機規范把方法區描述為堆的一個邏輯部分,但是它卻有一個別名叫做 Non-Heap(非堆),目的應該是與 Java 堆區分開來。
HotSpot 虛擬機中方法區也常被稱為 “永久代”,本質上兩者并不等價。僅僅是因為 HotSpot 虛擬機設計團隊用永久代來實現方法區而已,這樣 HotSpot 虛擬機的垃圾收集器就可以像管理 Java 堆一樣管理這部分內存了。但是這并不是一個好主意,因為這樣更容易遇到內存溢出問題。
調用格式:
類名.靜態變量名
類名.靜態方法名()
如果變量或者方法被 private 則代表該屬性或者該方法只能在類的內部被訪問而不能在類的外部被方法。
5、靜態代碼塊
靜態代碼塊定義在類中方法外, 靜態代碼塊在非靜態代碼塊之前執行(靜態代碼塊—非靜態代碼塊—構造方法)。 該類不管創建多少對象,靜態代碼塊只執行一次.
一個類中的靜態代碼塊可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果靜態代碼塊有多個,JVM將按照它們在類中出現的先后順序依次執行它們,每個代碼塊只會被執行一次。
靜態代碼塊對于定義在它之后的靜態變量,可以賦值,但是不能訪問.
靜態代碼塊通常用來對靜態變量進行一些初始化操作,比如定義枚舉類,還有我們熟悉的單例模式同樣也用到了靜態代碼塊
6、靜態內部類
靜態內部類與非靜態內部類之間存在一個最大的區別,我們知道非靜態內部類在編譯完成之后會隱含地保存著一個引用,該引用是指向創建它的外圍內,但是靜態內部類卻沒有。
沒有這個引用就意味著:
它的創建是不需要依賴外圍類的創建。
它不能使用任何外圍類的非static成員變量和方法。
代碼舉例(靜態內部類實現單例模式):
public class Singleton {// 聲明為 private 避免調用默認構造方法創建對象private Singleton() {}// 聲明為 private 表明靜態內部該類只能在該 Singleton 類中被訪問private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getUniqueInstance() {return SingletonHolder.INSTANCE;}
}
當 Singleton 類加載時,靜態內部類 SingletonHolder 沒有被加載進內存。只有當調用 getUniqueInstance()方法從而觸發 SingletonHolder.INSTANCE 時 SingletonHolder 才會被加載,此時初始化 INSTANCE 實例,并且 JVM 能確保 INSTANCE 只被實例化一次。
這種方式不僅具有延遲初始化的好處,而且由 JVM 提供了對線程安全的支持。
7、靜態導包
靜態導包格式:import static
這兩個關鍵字連用可以指定導入某個類中的指定靜態資源,并且不需要使用類名調用類中靜態成員,可以直接使用類中靜態成員變量和成員方法
靜態導包在書寫代碼的時候確實能省一點代碼,可以直接調用里面的靜態成員,但是會影響代碼可讀性,所以開發中一般情況下不建議這么使用。
8、靜態變量和實例變量
static修飾的成員變量叫做靜態變量【也叫做類變量】,靜態變量是屬于這個類,而不是屬于是對象。沒有被static修飾的成員變量叫做實例變量,實例變量是屬于這個類的實例對象。java規定static是不允許用來修飾局部變量的。
靜態變量和實例變量的區別
靜態變量:靜態變量由于不屬于任何實例對象,屬于類的,所以在內存中只會有一份,在類的加載過程中,JVM只為靜態變量分配一次內存空間。
實例變量:每次創建對象,都會為每個對象分配成員變量內存空間,實例變量是屬于實例對象的,在內存中,創建幾次對象,就有幾份成員變量。
訪問靜態變量和靜態方法的兩種方法:
靜態變量:
類名.靜態變量
對象.靜態變量(不推薦)
靜態方法:
類名.靜態方法
對象.靜態方法(不推薦)
靜態成員變量雖然獨立于對象,但是不代表不可以通過對象去訪問,所有的靜態方法和靜態變量都可以通過對象訪問【只要訪問權限足夠允許就行】。
this也是可以訪問static的變量的!
9、static靜態方法
static修飾的方法也叫做靜態方法,其實我們最熟悉的static靜態方法就是main方法。
由于對于靜態方法來說是不屬于任何實例對象的,this指的是當前對象,因為static靜態方法不屬于任何對象,所以就談不上this了。
還有一點就是:構造方法不是靜態方法!
x.static注意事項:
1、靜態只能訪問靜態。
2、非靜態既可以訪問非靜態的,也可以訪問靜態的。