"java深度歷險(xiǎn)"一書(shū)在講解“類裝載”的一章中,舉了以下的例子:

引用

Java代碼

  1. public interface Assembly{??
  2. public void start();;??
  3. }??
  4. public class Word implements Assembly{??
  5. static{??
  6. ??????? System.out.println("Word static initialization!");;??
  7. ??? }??????
  8. public void start();{??
  9. ??????? System.out.prinlnt("Word starts");;??
  10. ??? }??
  11. }??
  12. public class Office{??
  13. public static void main(String args[]); throws Exception{??
  14. ??????? Office off = new Office();;??
  15. ??????? System.out.println("類別準(zhǔn)備載入");;??
  16. ??????? Class c = Class.forName(args[0],true,off.getClass();.getClassLoader(););;??
  17. ??????? System.out.println("類別準(zhǔn)備實(shí)例化");;??
  18. ??????? Object o = c.newInstance();;??
  19. ??????? Object o2= c.newInstance();;??
  20. ?? }??
  21. }?

執(zhí)行java Office Word,運(yùn)行結(jié)果如下:
“Loaded Office”
“類別準(zhǔn)備載入”
“Loaded Accembly”
“Loaded Word””
“Word static initialization”
“類別準(zhǔn)備實(shí)體化”。
但是如果將Office.java中Class.forName(args[0],true,off.getClass().getClassLoader())中的true變?yōu)閒alse,再執(zhí)行java Office Word結(jié)果顯示為:
“Loaded Office”
“類別準(zhǔn)備載入”
“Loaded Accembly”
“Loaded Word””
“類別準(zhǔn)備實(shí)體化”
“Word static initialization”。

顯然兩次紅字部分順序相反,及static塊執(zhí)行的順序不同。此書(shū)作者提出了原因,原文:

引用

“過(guò)去很多java書(shū)上提到靜態(tài)初始化(static initializion block)時(shí),都會(huì)說(shuō)靜態(tài)初始化區(qū)塊只是在類第一次載入的時(shí)候才會(huì)被調(diào)用僅僅一次??墒巧厦孑敵鰠s發(fā)現(xiàn)即使類被載入了,其靜態(tài)初始化區(qū)塊也沒(méi)有被調(diào)用,而是在第一次調(diào)用newInstance方法時(shí),靜態(tài)初始化塊才被真正調(diào)用,應(yīng)該改成-靜態(tài)初始化塊只是在類被第一次實(shí)體化的時(shí)候才會(huì)被僅僅調(diào)用一次?!?/em>

其實(shí),該書(shū)作者的上述描述有誤。通過(guò)一個(gè)試驗(yàn),就可以看出謬誤所在。

Java代碼

  1. public class TestA{??
  2. static{??
  3. ?????? System.out.println("Static block executed!");;??
  4. ??? }??????
  5. }??
  6. public class Test{??
  7. public static void main(String args[]);{??
  8. ?????? Test test = new Test();;??
  9. ?????? Class.forName("TestA",true,test.getClass();.getClassLoader(););;??
  10. ?? }??
  11. }?

運(yùn)行一下,相信大家一定可以看到,“Static block executed!”的輸出。這與

引用

而是在第一次調(diào)用newInstance方法時(shí),靜態(tài)初始化塊才被真正調(diào)用

的說(shuō)法矛盾。
其實(shí)我想事實(shí)是這樣的:
一個(gè)類的運(yùn)行,JVM做會(huì)以下幾件事情 1、類裝載 2、鏈接 3、初始化 4、實(shí)例化;而初始化階段做的事情是初始化靜態(tài)變量和執(zhí)行靜態(tài)方法等的工作。所以,當(dāng)Class.forName(args[0],true,off.getClass().getClassLoader());中的true變?yōu)閒alse的時(shí)候,就是告訴JVM不需再load class之后進(jìn)行initial的工作。這樣,將initial的工作推遲到了newInstance的時(shí)候進(jìn)行。所以,static塊的絕對(duì)不是什么“只是在類被第一次實(shí)體化的時(shí)候才會(huì)被僅僅調(diào)用一次”,而應(yīng)該是在類被初始化的時(shí)候,僅僅調(diào)用一次。


文章來(lái)源:http://x-spirit.spaces.live.com/Blog/cns!CC0B04AE126337C0!817.entry