Java中final與static final的區別

yangxi_001發表於2017-06-08

看到一個程式講final與static final的區別,

class SelfCounter{
          private static int counter;
          private int id = counter ++;
          
          public String toString(){
                    return "SelfCounter :" + id;
          }
}

class WithFinalFields{
          static final SelfCounter wffs = new SelfCounter();
          final SelfCounter wff = new SelfCounter();
          
          
          public String toString(){
                    return "wff = " + wff + "\n wffs = " + wffs;
          }
}

public class E18_StaticFinal {
          public static void main(String[] args) {
                    System.out.println("First Object :");
                    System.out.println(new WithFinalFields());
                    System.out.println("Second Object: ");
                    System.out.println(new WithFinalFields());
          }
}
,執行結果是
First Object :
wff = SelfCounter :1
 wffs = SelfCounter :0
Second Object: 
wff = SelfCounter :2
 wffs = SelfCounter :0 


結論:

static的常量在類載入的時候被初始化,而例項常量在例項化的時候被初始化。

其實上面的過程很簡單。

第一次例項化WithFinalFields的時候,虛擬機器發現該類沒有被載入,於是先載入類,載入類的同時需要初始化類的所有static無論是變數、常量還是塊,於是wffs需要例項化一個SelfCounter物件,這個時候虛擬機器發現SelfCounter類也沒有被載入,於是載入SelfCounter類,同時初始化static變數counter為0,載入SelfCounter類完畢,開始例項化SelfCounter物件,初始化id為0(此時counter為0),同時counter變為1,這時SelfCounter物件的例項化完畢,並被賦值給WithFinalFields類的wffs常量,載入WithFinalFields類的過程完畢,開始正式例項化WithFinalFields物件,初始化wff常量,又需要例項化一個SelfCounter物件,這時虛擬機器發現SelfCounter類已經被載入,於直接開始例項化SelfCounter物件,初始化id為1(此時counter為1),同時counter變為2,例項化WithFinalFields物件完畢,此時wffs的id為0,wff的id為1。

第二次例項化WithFinalFields的時候,虛擬機器發現該類已經被載入,直接例項化,不會初始化static無論是變數、常量還是塊,於是直接初始化wff常量,需要例項化SelfCounter物件,該類也已經被載入,於是也直接例項化,初始化id為2(此時counter為2),同時counter變為3,例項化SelfCounter物件完畢,同時例項化WithFinalFields物件完畢,此時wffs的id仍然為0,wff的id為2。

重點是靜態的東西只會被初始化一次,發生在類載入的時候。

相關文章