本篇文章是看《effective java》第17條有感,在其基礎上還是有所擴充。本篇文章主要探究的是:在類繼承之後,建立子類對象,對父類構造器的調用,以及類初始化的順序(即父類域的初始化,子類域的初始化)。對於這樣的分析,別什麼理論不理論,我的解決方案就是先編個程看看,實際情況是什麼樣,要是和自己理解的不一樣,再查資料,補充自己的理論體系。所以不廢話了,看代碼。
class SuperClass{public static String superStaticField="父類===靜態域";public String superField="父類===變數";static{System.out.println(superStaticField);System.out.println("父類===靜態初始化塊");}{System.out.println(superField);System.out.println("父類===初始化塊");}public SuperClass(){System.out.println("父類構造器");}}public class SubClass extends SuperClass {public static String subStaticField="子類===靜態域";public String subField="子類===變數";static{System.out.println(subStaticField);System.out.println("子類===靜態初始化塊");}{System.out.println(subField);System.out.println("子類===初始化塊");}public SubClass(){System.out.println("子類構造器");}public static void main(String[] args){System.out.println("----------------");new SubClass();}}
輸出的結果是:
父類===靜態域
父類===靜態初始化塊
子類===靜態域
子類===靜態初始化塊
----------------
父類===變數
父類===初始化塊
父類構造器
子類===變數
子類===初始化塊
子類構造器
從代碼到輸出結果我們可以看到一清二楚,我們實現了類的繼承,那首先要先有個父類,所以java做的也對,就是先初始化父類,先將父類的.class檔案載入進來,有了父類然後再載入子類。由於靜態域是類固有的域,在沒有對象之前就已經存在,是在編譯好後就已存在的域,所以在編譯好後,父類的靜態域和子類的靜態域都已經初始化好了,所以先列印的就是靜態域。然後開始類的一般變數的初始化,當然首先是從父類開始的,這也非常理解,只有在父類的所有情況全部穩定之後,子類才能進行狀態的初始化,要不然子類就沒法用父類的東西了。
然後我們再做個實驗,把main方法裡的所有語句都注釋掉是什麼情況,你會看到只有分割線(--------------)上面的輸出了。這也剛好證實了,類的靜態域是在編譯時間候就已經初始化存在了的,是與類共生的,即使是沒有建立對象也能夠使用。 這有相當的好處,這也是《effective java》裡講的另一條,就是靜態工廠的說法,在這裡就不展開了。
下面我們從這個例子中衍生出其他的問題,其實也是繼承出現的問題,為了突出這個問題,下面讓我把代碼簡化。
import java.util.*;;class Super{public Super(){overrideMe();}public void overrideMe(){}}public class Sub extends Super{private final Date date;Sub(){date=new Date();} public void overrideMe(){System.out.println(date);}public static void main(String[] args){ System.out.println("------輸出:"); Sub sub=new Sub();sub.overrideMe();}}這個輸出是什麼呐。
-------輸出:
null
Fri Mar 27 15:59:56 CST 2015
第一個輸出是null,原因就是從在載入父類構造器的時候,父類構造器調用了overrideMe()方法,此方法在子類中被覆蓋,所以在調用的時候就調動了還沒有初始化的date,當然就是null了。這個問題其實分析起來並不難,主要討論的就是我們繼承java中的工具類的時候,有沒有考慮到會出現這種情況,以及如何避免這種情況的發生。《effective java》的做法是盡量使用組合的形式來擴充我們的類。