初始化(initialization)其實(shí)包含兩部分:
1.類的初始化(initialization class & interface)
2.對象的創(chuàng)建(creation of new class instances)。
因為類的初始化其實(shí)是類加載(loading of classes)的最后一步,所以很多書中把它歸結(jié)為“對象的創(chuàng)建”的第一步。其實(shí)只是看問題的角度不同而已。為了更清楚的理解,這里還是分開來。
順序:
應(yīng)為類的加載肯定是第一步的,所以類的初始化在前。大體的初始化順序是:
類初始化 -> 子類構(gòu)造函數(shù) -> 父類構(gòu)造函數(shù) -> 實(shí)例化成員變量 -> 繼續(xù)執(zhí)行子類構(gòu)造函數(shù)的語句
下面結(jié)合例子,具體解釋一下。
1。類的初始化(Initialization classes and interfaces),其實(shí)很簡單,具體來說有:
(a)初始化類(initialization of class),是指初始化static field 和執(zhí)行static初始化塊。
例如:
class Super {
??????? static String s = “initialization static field”; //初始化static field,其中“= “initialization static field” ”又叫做static field initializer
??????? // static初始化塊,又叫做static initializer,或 static initialization block
??????? static {
??????? System.out.println(“This is static initializer”);
}
}
btw,有些書上提到static initializer 和 static field initializer 的概念,與之對應(yīng)的還有 instance initializer 和 instance variable initializer。例子中的注釋已經(jīng)解釋了其含義。
(b)初始化接口(initialization of interface),是指初始化定義在該interface中的field。
*注意*
--initialization classes 時,該class的superclass 將首先被初始化,但其實(shí)現(xiàn)的interface則不會被初始化。
--initialization classes 時,該class的superclass,以及superlcass的superclass 會首先被遞歸地初始化,從java.lang.Object一直到該class為止。但initialiazation interface的時候,卻不需如此,只會初始化該interface本身。
--對于由引用類變量(class field)所引發(fā)的初始化,只會初始化真正定義該field的class。
--如果一個static field是編譯時常量(compile-time constant)(即定義為static final field),則對它的引用不會引起定義它的類的初始化。
為了幫助理解最后兩點(diǎn),請試試看下面的例子:
public class Initialization {
???????
??????? public static void main(String[] args) {
???????????????
??????????????? System.out.println(Sub.x); // Won't cause initialization of Sub, because x is declared by Super, not Sub.
???????????????????????????????????????? // 不會引起Sub類的初始化,因為x是定義在Super類中的
??????????????? System.out.println("-------------------------");
??????????????? System.out.println(Sub.y); // Won't cause initialization of Sub, because y is constant.
???????????????????????????????????????? // 不會引起Sub類的初始化,因為y是常量
??????????????? System.out.println("-------------------------");
??????????????? System.out.println(Sub.z = 2004); // Will cause initialization of Sub class
??// 將會引起Sub的初始化
??}
}
class Super{
??????? static int x = 2006;
}
class Sub extends Super {
???????
??????? static final int y = 2005;
???????
static int z;
???????
static {
??????????????? System.out.println("Initialization Sub");
??????? }
}
2。對象的創(chuàng)建(creation of new class instances),稍微有點(diǎn)煩瑣,具體的步驟如下
(a) 所有的成員變量—包括該類,及它的父類中的成員變量--被分配內(nèi)存空間,并賦予默認(rèn)值。(Btw,這里是第一次初始化成員變量)
(b) 為所調(diào)用的構(gòu)造函數(shù)初始化其參數(shù)變量。(如果有參數(shù))
(c) 如果在構(gòu)造函數(shù)中用this 調(diào)用了同類中的其他構(gòu)造函數(shù),則按照步驟(b)~(f)去處理被調(diào)用到的構(gòu)造函數(shù)。
(d) 如果在構(gòu)造函數(shù)中用super調(diào)用了其父類的構(gòu)造函數(shù),則按照步驟(b)~(f)去處理被調(diào)用到的父類構(gòu)造函數(shù)。
(e) 按照書寫順序,執(zhí)行instance initializer 和 instance variable initializer來初始化成員變量。(Btw,這里是第二次初始化成員變量)
(f) 按照書寫順序,執(zhí)行constructor的其余部分。
*注意*
成員變量其實(shí)都被初始化2次,第一次是賦予默認(rèn)值,第二次才是你想要設(shè)定的值。
最后看一個例子:
public class InitializationOrder {
??????? public static void main(String[] args) {
??????????????? Subclass sb = new Subclass();
??????? }
}
class Super{
???????
??????? static {
??????????????? System.out.println(1);
??????? }
???????
??????? Super(int i){
??????????????? System.out.println(i);
??????? }
}
class Subclass extends Super implements Interface{
???????
??????? static {
??????????????? System.out.println(2);
??????? }???????
???????
??????? Super su = new Super(4);
???????
??????? Subclass() {
??????????????? super(3);
??????????????? new Super(5);
??????? }
}
interface Interface{
??????? static Super su = new Super(0);
}
稍微解釋一下:
首先,Java虛擬機(jī)要執(zhí)行InitializationOrder類中的static 方法main(),這引起了類的初始化。開始初始化InitializationOrder類。具體的步驟略去不說。
接著,InitializationOrder類初始化完畢后,開始執(zhí)行main()方法。語句Subclass sb = new Subclass()將創(chuàng)建一個Subclass對象。加載類Subclass后對其進(jìn)行類初始化,但因為Subclass有一個父類Super,所以先初始化Super類,初始化塊static {System.out.println(1);}被執(zhí)行,打印輸出1;
第三,Super初始化完畢后,開始初始化Subclass類。static {System.out.println(2);}被執(zhí)行,打印輸出2;
第四,至此,類的加載工作全部完成。開始進(jìn)入創(chuàng)建Subclass的對象過程。先為Subclass類和其父類Super類分配內(nèi)存空間,這時Super su 被附值為null;
第五,執(zhí)行構(gòu)造函數(shù)Subclass()時,super(3)被執(zhí)行。如前面(d)所說,Super類的構(gòu)造函數(shù)Super(int i){….}被調(diào)用,并按照步驟(b)~(f)來處理。因此,遞歸調(diào)用Super類的父類Object類的構(gòu)造函數(shù),并按照步驟(b)~(f)來初始化Object類,不過沒有任何輸入結(jié)果。最后打印輸出3;
第六,如前面(e)所說,初始化成員變量su,其結(jié)果是打印輸出4;
第七,如前面(f)所說,執(zhí)行new Super(5),并打印輸出5;
最后,Subclass雖然實(shí)現(xiàn)了接口Interface,但是初始化它的時候并不會引起接口的初始化,所以接口Interface中的static Super su = new Super(0)自始至終都沒有被執(zhí)行到。
max做的小改動:
public class Test {
??? public static void main(String[] args) {
??????????? Subclass sb = new Subclass();
??? }
}
class SS{
?public SS(int i){
??System.out.println(i);
?}
}
class Super{
???
??? static {
??????????? System.out.println(1);
??? }
??? SS ss = new SS(100);
???
??? Super(int i){
??????????? System.out.println(i);
??? }
}
class Subclass extends Super implements Interface{
???
??? static {
??????????? System.out.println(2);
??? }???????
???
??? Super su = new Super(4);
???
??? Subclass() {
??????????? super(3);
??????????? new Super(5);
??? }
}
interface Interface{
??? static Super su = new Super(0);
}
--------------------
結(jié)果為:
1
2
100
3
100
4
100
5
posted on 2006-06-01 14:56
保爾任 閱讀(157)
評論(0) 編輯 收藏