Java中的static關鍵字解析

Java中的static關鍵字解析

本文轉子博客園,單擊此處閱讀原文

static關鍵字是很多朋友在編寫代碼和閱讀代碼時碰到的比較難以理解的一個關鍵字,也是各大公司的面試官喜歡在面試時問到的知識點之一。下面就先講述一下static關鍵字的用法和平常容易誤解的地方,最后列舉了一些面試筆試中常見的關于static的考題。以下是本文的目錄大綱:

一.static關鍵字的用途

二.static關鍵字的誤區

三.常見的筆試面試題

若有不正之處,希望諒解并歡迎批評指正。請尊重作者勞動成果,轉載請標明原文鏈接:

http://www.cnblogs.com/dolphin0520/p/3799052.html

一.static關鍵字的用途

在《Java編程思想》P86頁有這樣一段話:

“static方法就是沒有this的方法。在static方法內部不能調用非靜態方法,反過來是可以的。而且可以在沒有創建任何對象的前提下,僅僅通過類本身來調用static方法。這實際上正是static方法的主要用途。”

這段話雖然只是說明了static方法的特殊之處,但是可以看出static關鍵字的基本作用,簡而言之,一句話來描述就是:

方便在沒有創建對象的情況下來進行調用(方法/變量)。

很顯然,被static關鍵字修飾的方法或者變量不需要依賴于對象來進行訪問,只要類被加載了,就可以通過類名去進行訪問。

static可以用來修飾類的成員方法、類的成員變量,另外可以編寫static代碼塊來優化程序性能。

1)static方法

static方法一般稱作靜態方法,由于靜態方法不依賴于任何對象就可以進行訪問,因此對于靜態方法來說,是沒有this的,因為它不依附于任何對象,既然都沒有對象,就談不上this了。并且由于這個特性,在靜態方法中不能訪問類的非靜態成員變量和非靜態成員方法,因為非靜態成員方法/變量都是必須依賴具體的對象才能夠被調用。

但是要注意的是,雖然在靜態方法中不能訪問非靜態成員方法和非靜態成員變量,但是在非靜態成員方法中是可以訪問靜態成員方法/變量的。舉個簡單的例子:

在上面的代碼中,由于print2方法是獨立于對象存在的,可以直接用過類名調用。假如說可以在靜態方法中訪問非靜態方法/變量的話,那么如果在main方法中有下面一條語句:

MyObject.print2();

此時對象都沒有,str2根本就不存在,所以就會產生矛盾了。同樣對于方法也是一樣,由于你無法預知在print1方法中是否訪問了非靜態成員變量,所以也禁止在靜態成員方法中訪問非靜態成員方法。

而對于非靜態成員方法,它訪問靜態成員方法/變量顯然是毫無限制的。

因此,如果說想在不創建對象的情況下調用某個方法,就可以將這個方法設置為static。我們最常見的static方法就是main方法,至于為什么main方法必須是static的,現在就很清楚了。因為程序在執行main方法的時候沒有創建任何對象,因此只有通過類名來訪問。

另外記住,即使沒有顯示地聲明為static,類的構造器實際上也是靜態方法。

2)static變量

static變量也稱作靜態變量,靜態變量和非靜態變量的區別是:靜態變量被所有的對象所共享,在內存中只有一個副本,它當且僅當在類初次加載時會被初始化。而非靜態變量是對象所擁有的,在創建對象的時候被初始化,存在多個副本,各個對象擁有的副本互不影響。

static成員變量的初始化順序按照定義的順序進行初始化。

3)static代碼塊

static關鍵字還有一個比較關鍵的作用就是 用來形成靜態代碼塊以優化程序性能。static塊可以置于類中的任何地方,類中可以有多個static塊。在類初次被加載的時候,會按照static塊的順序來執行每個static塊,并且只會執行一次。

為什么說static塊可以用來優化程序性能,是因為它的特性:只會在類加載的時候執行一次。下面看個例子:

1

2

3

4

5

6

7

8

9

10

11

12

13classPerson{

privateDate birthDate;

publicPerson(Date birthDate) {

this.birthDate = birthDate;

}

booleanisBornBoomer() {

Date startDate = Date.valueOf("1946");

Date endDate = Date.valueOf("1964");

returnbirthDate.compareTo(startDate)>=0&& birthDate.compareTo(endDate) <0;

}

}

isBornBoomer是用來這個人是否是1946-1964年出生的,而每次isBornBoomer被調用的時候,都會生成startDate和birthDate兩個對象,造成了空間浪費,如果改成這樣效率會更好:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16classPerson{

privateDate birthDate;

privatestaticDate startDate,endDate;

static{

startDate = Date.valueOf("1946");

endDate = Date.valueOf("1964");

}

publicPerson(Date birthDate) {

this.birthDate = birthDate;

}

booleanisBornBoomer() {

returnbirthDate.compareTo(startDate)>=0&& birthDate.compareTo(endDate) <0;

}

}

因此,很多時候會將一些只需要進行一次的初始化操作都放在static代碼塊中進行。

二.static關鍵字的誤區

1.static關鍵字會改變類中成員的訪問權限嗎?

有些初學的朋友會將java中的static與C/C++中的static關鍵字的功能混淆了。在這里只需要記住一點:與C/C++中的static不同,Java中的static關鍵字不會影響到變量或者方法的作用域。在Java中能夠影響到訪問權限的只有private、public、protected(包括包訪問權限)這幾個關鍵字。看下面的例子就明白了:

提示錯誤"Person.age 不可視",這說明static關鍵字并不會改變變量和方法的訪問權限。

2.能通過this訪問靜態成員變量嗎?

雖然對于靜態方法來說沒有this,那么在非靜態方法中能夠通過this訪問靜態成員變量嗎?先看下面的一個例子,這段代碼輸出的結果是什么?

1

2

3

4

5

6

7

8

9

10

11

12publicclassMain {

staticintvalue =33;

publicstaticvoidmain(String[] args)throwsException{

newMain().printValue();

}

privatevoidprintValue(){

intvalue =3;

System.out.println(this.value);

}

}

View Code

這里面主要考察隊this和static的理解。this代表什么?this代表當前對象,那么通過new Main()來調用printValue的話,當前對象就是通過new Main()生成的對象。而static變量是被對象所享有的,因此在printValue中的this.value的值毫無疑問是33。在printValue方法內部的value是局部變量,根本不可能與this關聯,所以輸出結果是33。在這里永遠要記住一點:靜態成員變量雖然獨立于對象,但是不代表不可以通過對象去訪問,所有的靜態方法和靜態變量都可以通過對象訪問(只要訪問權限足夠)。

3.static能作用于局部變量么?

在C/C++中static是可以作用域局部變量的,但是在Java中切記:static是不允許用來修飾局部變量。不要問為什么,這是Java語法的規定。

三.常見的筆試面試題

下面列舉一些面試筆試中經常遇到的關于static關鍵字的題目,僅供參考,如有補充歡迎下方留言。

1.下面這段代碼的輸出結果是什么?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25publicclassTestextendsBase{

static{

System.out.println("test static");

}

publicTest(){

System.out.println("test constructor");

}

publicstaticvoidmain(String[] args) {

newTest();

}

}

classBase{

static{

System.out.println("base static");

}

publicBase(){

System.out.println("base constructor");

}

}

View Code

至于為什么是這個結果,我們先不討論,先來想一下這段代碼具體的執行過程,在執行開始,先要尋找到main方法,因為main方法是程序的入口,但是在執行main方法之前,必須先加載Test類,而在加載Test類的時候發現Test類繼承自Base類,因此會轉去先加載Base類,在加載Base類的時候,發現有static塊,便執行了static塊。在Base類加載完成之后,便繼續加載Test類,然后發現Test類中也有static塊,便執行static塊。在加載完所需的類之后,便開始執行main方法。在main方法中執行new Test()的時候會先調用父類的構造器,然后再調用自身的構造器。因此,便出現了上面的輸出結果。

2.這段代碼的輸出結果是什么?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35publicclassTest {

Person person =newPerson("Test");

static{

System.out.println("test static");

}

publicTest() {

System.out.println("test constructor");

}

publicstaticvoidmain(String[] args) {

newMyClass();

}

}

classPerson{

static{

System.out.println("person static");

}

publicPerson(String str) {

System.out.println("person "+str);

}

}

classMyClassextendsTest {

Person person =newPerson("MyClass");

static{

System.out.println("myclass static");

}

publicMyClass() {

System.out.println("myclass constructor");

}

}

View Code

類似地,我們還是來想一下這段代碼的具體執行過程。首先加載Test類,因此會執行Test類中的static塊。接著執行new MyClass(),而MyClass類還沒有被加載,因此需要加載MyClass類。在加載MyClass類的時候,發現MyClass類繼承自Test類,但是由于Test類已經被加載了,所以只需要加載MyClass類,那么就會執行MyClass類的中的static塊。在加載完之后,就通過構造器來生成對象。而在生成對象的時候,必須先初始化父類的成員變量,因此會執行Test中的Person person = new Person(),而Person類還沒有被加載過,因此會先加載Person類并執行Person類中的static塊,接著執行父類的構造器,完成了父類的初始化,然后就來初始化自身了,因此會接著執行MyClass中的Person person = new Person(),最后執行MyClass的構造器。

3.這段代碼的輸出結果是什么?

1

2

3

4

5

6

7

8

9

10

11

12

13publicclassTest {

static{

System.out.println("test static 1");

}

publicstaticvoidmain(String[] args) {

}

static{

System.out.println("test static 2");

}

}

View Code

雖然在main方法中沒有任何語句,但是還是會輸出,原因上面已經講述過了。另外,static塊可以出現類中的任何地方(只要不是方法內部,記住,任何方法內部都不行),并且執行是按照static塊的順序執行的。

參考資料:

http://lavasoft.blog.51cto.com/62575/18771/

http://www.51cto.com/specbook/24/35011.htm

http://blog.csdn.net/zhu_apollo/article/details/1888219

http://blog.sina.com.cn/s/blog_70b845780100n9zz.html

http://hi.baidu.com/yuiezt/item/b71ff5fbfe9c385cc8f3370d

http://bbs.csdn.net/topics/330251070

http://yezixingchen.iteye.com/blog/1597186

《Java編程思想》

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容

  • 作者:海子原文地址:http://www.cnblogs.com/dolphin0520/ static關鍵字是很...
    IT程序獅閱讀 1,229評論 0 16
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,711評論 18 399
  • 文章大綱:1.為什么static會有這樣的效果?2.static的使用3.static誤區4.static面試題 ...
    檸檬烏冬面閱讀 5,875評論 3 43
  • 猶愛慢節奏的電影,例如《面包和湯和貓咪好天氣》主角亞紀子原本是一位與媽媽一起生活的單身編輯。由于媽媽突然去世,公司...
    中三二閱讀 210評論 0 1
  • 張勛復辟,有種說法是,在張勛的提議下,參加會議的各方代表在一件黃緞子上簽名,以是同意宣統皇帝復位。 傳說張勛復辟失...
    c0ee46805838閱讀 322評論 0 0