子類重寫父類方法後的呼叫規則
阿新 • • 發佈:2019-01-05
例題:
(單選題) 下面程式碼的輸出是什麼?- publicclass Base {
- private String baseName= "base";
- public Base(){
- callName();
- }
- publicvoid callName(){
- System.out.println(baseName);
- }
- staticclass Sub extends Base{
- private String baseName = "sub";
-
public
- System.out.println(baseName);
- }
- }
- publicstaticvoid main(String[] args){
- Base b = new Sub();
- }
- }
A.null
B.sub
C.base
答案:A
為了能更好的分析程式碼執行過程, 做原有程式碼做一些變動如下:
- publicclass Base {
- private String baseName= "base";
-
public
- System.out.println("Constructor Base : " + baseName);
- System.out.println("before Base callName() -----" );
- callName();
- System.out.println("after Base callName() -----" );
- }
- publicvoid callName(){
-
System.out.println("& " + baseName);
- }
- staticclass Sub extends Base{
- private String baseName = "sub";
- public Sub(){
- System.out.println("Constructor Sub : " + baseName);
- }
- @Override
- publicvoid callName(){
- System.out.println("# " + baseName);
- }
- }
- publicstaticvoid main(String[] args){
- new Sub();
- }
- }
輸出結果:
- Constructor Base : base
- before Base callName() -----
- # null
- after Base callName() -----
- Constructor Sub : sub
再將main方法做如下變動:
- publicstaticvoid main(String[] args){
- Base b = new Sub();
- b.callName();
- }
輸出結果:
- Constructor Base : base
- before Base callName() -----
- # null
- after Base callName() -----
- Constructor Sub : sub
- # sub
綜上所述, 此時執行的是子類Sub的callName() 方法,
new Sub();在創造派生類的過程中首先建立基類物件,然後才能建立派生類。 建立基類即預設呼叫Base()方法,在方法中呼叫callName()方法,由於派生類中存在此方法,則被呼叫的callName()方法是派生類中的方法,此時派生類還未構造,所以變數baseName的值為null 先成員變數再構造方法,先父類再子類 多型表現:有同名方法執行子類的 執行 Base b = new Sub();時,由於多型 b編譯時表現為Base類特性,執行時表現為Sub類特性, Base b = new Sub();不管是哪種狀態都會呼叫Base構造器執行callName()方法; 執行方法時,由於多型表現為子類特性,所以會先在子類是否有 callName(); 而此時子類尚未初始化(執行完父類構造器後才會開始執行子類),如果有 就 執行(此時, 因為還沒有呼叫子類建構函式, 所以子類的 baseName 輸出為 null),沒有再去父類尋找。