又到了讀代碼了解java知識(shí)的時(shí)間了掂为。今天我們來了解下java中的static關(guān)鍵字荔棉,來看看它的作用和一些相關(guān)原理蔫劣。
package com.xingshulin;
public class StaticTest {
private String a = "I am a! ";
private static String b = "I am b! ";
// 構(gòu)造函數(shù)
public StaticTest() {
System.out.println("I am constructor!");
}
// static代碼塊
static {
System.out.println("I am static block 1!");
// System.out.println(a);
}
public static void main(String args[]) {
// 生成StaticTest類的對(duì)象
StaticTest st = new StaticTest();
// 打印變量a
System.out.println(st.a);
// 打印變量b
System.out.println(StaticTest.b);
System.out.println(b);
// 運(yùn)行靜態(tài)方法
staticMethod();
StaticTest.staticMethod();
// 運(yùn)行非靜態(tài)方法
st.nonStaticMethod();
}
// 靜態(tài)方法
public static void staticMethod() {
System.out.println("I am static method!");
//System.out.println(a);
}
// 實(shí)例方法(非靜態(tài)方法)
public void nonStaticMethod() {
System.out.println("I am non static method");
System.out.println(a);
System.out.println(b);
}
// static代碼塊
static {
System.out.println("I am static block 2!");
}
private static String c;
// static代碼塊
static {
System.out.println("I am static block " + c + "!");
}
}
運(yùn)行結(jié)果如下:
I am static block 1!
I am static block 2!
I am static block null!
I am constructor!
I am a!
I am b!
I am b!
I am static method!
I am static method!
I am non static method
I am a!
I am b!
這段代碼很簡單鞭盟,但是也足夠說明static關(guān)鍵字的作用了。從上面的例子中我們可以看到static的三種表現(xiàn)形式:static變量、static方法劈彪、static代碼塊
static變量
在代碼中的變量b和c就是static變量竣蹦,有人會(huì)問了,那變量a是什么沧奴?其實(shí)變量a叫實(shí)例變量痘括。它們的區(qū)別是變量a是在創(chuàng)建對(duì)象后分配的;而static變量b和c不同滔吠,static變量被所有對(duì)象共享纲菌,在內(nèi)存中只有一個(gè)副本,是在類加載的過程中分配到JVM的方法區(qū)中屠凶。static變量可用類名直接訪問驰后,如代碼:
在這里我們多說一下變量c,我們是沒有給它賦初值的矗愧,但是并沒有造成編譯出錯(cuò)灶芝,而且在打印的時(shí)候發(fā)現(xiàn)它的值被自動(dòng)置為了null(因?yàn)槭荢tring類型)。這說明static變量不像局部變量那樣需要賦初值才能編譯唉韭,我認(rèn)為主要的原因應(yīng)該是static變量在方法區(qū)分配夜涕,而局部變量在棧中分配,方法區(qū)的內(nèi)存可以動(dòng)態(tài)變化属愤,而棧的大小在線程運(yùn)行前就需要是已知的女器,所以局部變量必須有初值(此處留坑,不一定理解的對(duì))
static方法
和static變量類似住诸,static方法也不需要?jiǎng)?chuàng)建對(duì)象就可以被所有對(duì)象調(diào)用驾胆,并可直接通過類名調(diào)用。
也正是由于這個(gè)特性贱呐,static方法中不能包含this等和對(duì)象有關(guān)的關(guān)鍵字丧诺,更不能包含實(shí)例變量和實(shí)例方法,否則編譯會(huì)出現(xiàn)問題:
但是也如上圖所示奄薇,實(shí)例方法中卻可以包含實(shí)例變量和static變量驳阎,原因很簡單,就不贅述了馁蒂。
static代碼塊
static關(guān)鍵字還有一個(gè)比較關(guān)鍵的作用就是用來形成static代碼塊以優(yōu)化程序性能呵晚。static塊可以置于類中的任何地方,類中可以有多個(gè)static塊沫屡。在類初次被加載的時(shí)候饵隙,會(huì)按照static塊的順序來執(zhí)行每個(gè)static塊,并且只會(huì)執(zhí)行一次沮脖。
從上面的代碼結(jié)果來看癞季,的確是在類加載的時(shí)候就進(jìn)行了static塊的運(yùn)行劫瞳,因?yàn)樗械拇a塊打印都在構(gòu)造函數(shù)之前。
而且和static方法一樣绷柒,static代碼塊中不能包含this等和對(duì)象有關(guān)的關(guān)鍵字,更不能包含實(shí)例變量和實(shí)例方法涮因,否則編譯會(huì)出現(xiàn)問題: