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