"java深度歷險(xiǎn)"一書(shū)在講解“類裝載”的一章中,舉了以下的例子:
引用
Java代碼
- public interface Assembly{??
- public void start();;??
- }??
-
- public class Word implements Assembly{??
- static{??
- ??????? System.out.println("Word static initialization!");;??
- ??? }??????
-
- public void start();{??
- ??????? System.out.prinlnt("Word starts");;??
- ??? }??
- }??
-
- public class Office{??
- public static void main(String args[]); throws Exception{??
- ??????? Office off = new Office();;??
- ??????? System.out.println("類別準(zhǔn)備載入");;??
- ??????? Class c = Class.forName(args[0],true,off.getClass();.getClassLoader(););;??
- ??????? System.out.println("類別準(zhǔn)備實(shí)例化");;??
- ??????? Object o = c.newInstance();;??
- ??????? Object o2= c.newInstance();;??
- ?? }??
- }?
執(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代碼
- public class TestA{??
- static{??
- ?????? System.out.println("Static block executed!");;??
- ??? }??????
- }??
-
- public class Test{??
- public static void main(String args[]);{??
- ?????? Test test = new Test();;??
- ?????? Class.forName("TestA",true,test.getClass();.getClassLoader(););;??
- ?? }??
- }?
運(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