引用:
文中提到
子類的初始化過程。
父類static修飾的模組
子類static修飾模組
父類例項變數和非static塊
父類對應建構函式。當子類對應建構函式中沒有顯示呼叫時呼叫的是父類預設的建構函式。
子類例項變數和非static塊
子類建構函式
上述中如子類例項變數和非static塊,這兩者的執行順序取決於在類檔案中的書寫順序,靜態的與之相同,也是取決於類檔案中的書寫順序
現在我們思考,將
1.類的成員變數在宣告處進行初始化
或者在2.使用**塊初始化
或者在3..建構函式中初始化
的應用場景及區別
上述三種的對應**分別是:)
1.
public class son extends father2.*/public son()
@override
public void override()
}
public class son extends father3.public son()
@override
public void override()
}
public class son extends father上面的分析可以對應至靜態成員變數,只是分析時需要按靜態成員的初始化順序分析*/public son()
@override
public void override()
}
1.既然在宣告處直接初始化和**塊初始化方式僅僅取決於**的書寫順序,那麼兩者的作用在初始化成員變數上是相同的,但是**塊除了能夠初始化成員變數之外,還能夠做一些其他工作,因此寫**時傾向於在宣告處直接初始化成員變數(如果可以的話),而在**塊中做一些環境檢查,變數初始化檢查,以及其他一些除初始化之外的額外的動作,這些動作經常不涉及成員方法的呼叫
2.在宣告處直接初始化這種方式無非是想給成員變數乙個預設值,這種方式往往對映著無參構造器或者其他的缺少某個不帶重要的引數的構造器的使用,這兩種方式初始化成員變數效果上是相同的,如果你在建構函式中只是簡單的賦值,請考慮將這部分邏輯移至宣告處直接初始化,而在建構函式中去使用某個成員方法(如果需要的話)
我發現的錯誤:
class parent上述**的輸出結果是:void add(int y)
} class child extends parent
public static void main(string args)
}
依據上面的分析,其呼叫過程應該是:
1.在main函式中檢測到new呼叫,嘗試去載入類,發現此時尚未載入child,載入child類
2.發現child類繼承自parent,轉去載入parent
3.parent沒有靜態成員或者靜態**塊,載入結束
4.呼叫new位元組碼指令,此時父類載入完畢,首先初始化父類成員變數,此時parent.x=10;
5.發現父類存在成員變數,初始化之,無非靜態**塊,進行第6步
6.呼叫父類建構函式,在其中發現了add(2)方法,向虛擬機器棧推送棧幀,發現當前類型別資訊是child。
7.呼叫子類的add(2)方法,注意此時子類成員變數並未初始化,建構函式也未呼叫,x只是在編譯時賦了初值0;
8.呼叫子類add(2)之後,此時child.x=2;
9.父類構造函式呼叫完畢,開始準備呼叫子類建構函式
10.初始化子類的成員變數,即執行子類的int x=9,此時child.x=9;
11.呼叫子類的建構函式,子類建構函式無任何操作,整個呼叫過程結束。
因此最終輸出
10,9
基於此,你也應該能夠解釋為什麼有時候在子類成員變數宣告處直接初始化但是在執行時仍會出現空指標異常的現象
tips:
子類繼承父類,初始化以及方法呼叫順序
父類public class parenta public parenta public void function public class subclassb extends parenta public subclassb public void function public static ...
Java中父類 子類初始化順序
測試結果 父類靜態 塊 子類靜態 塊 父類成員變數初始化parent common block test 父類有參構造方法ppp 子類成員變數初始化son common block test 子類有參構造方法ppp sss 靜態 塊只能生成一次 父類成員變數初始化parent common bloc...
父類,子類初始化 2
載入類時,先父類靜態,再子類靜態,然後是子類中main方法,main方法中如果有生成子類物件的語句,先找到子類建構函式,因為每個子類建構函式裡頭都會有super語句 jdk預設或者自己提供,且預設在建構函式中第一行 則先初始化父類非靜態,然後父類構造,再然後是子類非靜態,子類建構函式 除super之...