讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議32:靜態變量一定要先聲明後賦值 >

建議32:靜態變量一定要先聲明後賦值

這標題看著讓人很納悶,什麼叫做變量一定要先聲明後賦值?Java中的變量不都是先聲明後使用的嗎?難道還能先使用後聲明?能不能暫且不說,我們先來看一個例子,代碼如下:


public class Client{

public static int i=1;

static{

i=100;

}

public static void main(Stringargs){

System.out.println(i);

}

}


這段程序很簡單,輸出100嘛!對,確實是100,我們再稍稍修改一下,代碼如下:


public class Client{

static{

i=100;

}

public static int i=1;

public static void main(Stringargs){

System.out.println(i);

}

}


注意,變量i的聲明和賦值調換了位置,現在的問題是:這段程序能否編譯?如果可以編譯那輸出是多少?還要注意:這個變量i可是先使用(也就是賦值)後聲明的。

答案是:可以編譯,沒有任何問題,輸出是1。對,你沒有看錯,輸出確實是1,而不是100。僅僅調換了一下位置,輸出就變了,而且變量i還真是先使用後聲明的,難道這世界真的顛倒了?

這要從靜態變量的誕生說起了,靜態變量是類加載時被分配到數據區(Data Area)的,它在內存中只有一個拷貝,不會被分配多次,其後的所有賦值操作都是值改變,地址則保持不變。我們知道JVM初始化變量是先聲明空間,然後再賦值的,也就是說:


int i=100;


在JVM中是分開執行,等價於:


int i;//分配地址空間

i=100;//賦值


靜態變量是在類初始化時首先被加載的,JVM會去查找類中所有的靜態聲明,然後分配空間,注意這時候只是完成了地址空間的分配,還沒有賦值,之後JVM會根據類中靜態賦值(包括靜態類賦值和靜態塊賦值)的先後順序來執行。對於程序來說,就是先聲明了int類型的地址空間,並把地址傳遞給了i,然後按照類中的先後順序執行賦值動作,首先執行靜態塊中i=100,接著執行i=1,那最後的結果就是i=1了。

哦,如此而已,那再問一個問題:如果有多個靜態塊對i繼續賦值呢?i當然還是等於1了,誰的位置最靠後誰有最終的決定權。

有些程序員喜歡把變量定義放到類的底部,如果這是實例變量還好說,沒有任何問題,但如果是靜態變量,而且還在靜態塊中進行了賦值,那這結果可就和你期望的不一樣了,所以遵循Java通用的開發規範「變量先聲明後使用」是一個良好的編碼風格。

注意 再次重申變量要先聲明後使用,這不是一句廢話。