建議32: 靜态變量一定要先聲明後指派
這标題看着讓人很納悶,什麼叫做變量一定要先聲明後指派?Java中的變量不都是先聲明後使用的嗎?難道還能先使用後聲明?能不能暫且不說,我們先來看一個例子,代碼如下:
1 public class Client {
2 public static int i=1;
3 static{
4 i=100;
5 }
6 public static void main(String[] args) {
7 System.out.println(i);
8 }
9 }
這段程式很簡單,輸出100嘛!對,确實是100,我們再稍稍修改一下,代碼如下:
1 public class Client {
2 static {
3 i = 100;
4 }
5 public static int i = 1;
6
7 public static void main(String[] args) {
8 System.out.println(i);
9 }
10 }
注意,變量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通用的開發規範“變量先聲明後使用”是一個良好的編碼風格。
注意 再次重申變量要先聲明後使用,這不是一句廢話。
作者:SummerChill |