1. 程式人生 > >Java final欄位的初始化詳解

Java final欄位的初始化詳解

JAVA的final關鍵詞可以用在三方面,一是欄位,二是方法,三是類,本文主要討論final欄位的幾種初始化方法.
首先用我個人通俗語言來解釋一下final欄位的意思,就是final如果初始化值,就不允許對它進行賦值運算,不允許再修改它的值了,JAVA術語叫final欄位為常量.
注:本文的示例程式碼都沒有寫main方法,但程式碼都可以編譯通過,自己可以再建一個類來進行測試.
第一種情況是最常用的,就是在宣告一個常量,並初始化它的值.
public class Test{
final int i=0;        //在宣告時就初始始常量的值.
}

第二種情況就是宣告常量時,不初始化它的值,通過構造方法或塊(關於塊大家可以看我的”什麼是java塊”)來初始化.
1.通過構造方法來初始化.
public class Test{
final int i;    //宣告時未初始化,如果常量不通過構造方法或塊初始化會報錯的
Test(){
i=1;    //通過預設的無參構造方法初始化i=1,
//如果只有預設的無參構造方法,這樣每個物件的fianl常量都為一個值
}
//or
Test(int n){
i=n;    //通過構造方法過載,用有參的構造方法的引數來初始化常量為你想要的值
//這樣每個物件的i屬性可以為不同的值
}
}

2,通過塊來初始化常量.
public class Test{
final int i;

//在class只打{},這樣的格式語句稱為塊
{
i=1;    //這樣初始化每一個物件的i屬性都是1,以後不可以改它的值為其它
//不可以再在建構函式裡初始化i的值,因為塊已經把常量初始化了,再初始化就是修改它的值
}

}


為什麼這樣寫可以呢,這個涉及到JAVA的成員初始化順序,大家可以看我整理寫的XXXX,或直接看thinkingInJava的第四章第四小節,網上有thinkingInJava的電子書下載.
3,初始化靜態常量.
public class Test{
static final int i;
static{
i=1;
}
}

靜態常量比較特別,不能通過構造方法或非靜態塊來進行初始化,從設計角度來考慮,如果可以通過構造方法或非靜態塊來進行初始化,那每new一個物件都會對靜態的常量進行再一次的賦值操作,也就是說修改它的值,這樣與常量不能修改的意思相沖突.
一個類的靜態屬性是所有物件公有的,而非靜態屬性是每一個物件私有的,所以我們只能用靜態塊對static常量初始化,或通過宣告時就初始化,而非靜態常量可以構造方法,塊,宣告時初始化三種初始化方法.
從成員的初始化順序來考慮這個問題.當直接通過第一類名.屬性或類名.方法名這樣的方式訪問,都會自動先呼叫static塊,然後再呼叫靜態屬性,如果是直接呼叫靜態方法,最後才進行靜態方法的呼叫,而以後直接”類名.”訪問時,都不會再呼叫static塊,因為靜態的是共享的,只用初始化一次.擴充套件一下,從這裡大家想到為什麼不可以在靜態的方法裡呼叫非靜態成員屬性不?因為當直接通過類名.方法名呼叫非靜態的成員屬性時,有可以成員屬性沒有初始化,是通過構造方法new時才初始化,這樣就有可能導致空引用的存在.sun程式設計師為了避免這樣的情況出現,只有規定靜態方法不能呼叫非靜態屬性.