2015-05-19 82 views
9

請考慮下面的代碼。創建基類對象時的運行時多態性

class Base{ 
    Base() { 
     print(); 
    } 
    void print() { 
     System.out.println("Base"); 
    } 
} 

class Child extends Base{ 
    int i = 4; 
    public static void main(String[] args){ 
     Base base = new Child(); 
     base.print(); 
    } 
    void print() { 
     System.out.println(i); 
    } 
} 

該程序將打印0,4。

我的理解是,要執行的方法將根據實際對象的類別進行選擇,因此在這種情況下爲Child。所以當Base的構造函數被稱爲打印方法Child被調用,所以這將打印0,4。

請告訴我是否理解正確? 如果是,我還有一個問題,而基類構造函數運行時,JVM如何調用Child的方法,因爲Child的對象沒有創建?

回答

7

[...]將根據班級的實際對象

是來選擇要執行的方法,你的理解是正確的:該方法是基於的類型來選擇對象被創建,所以呼叫被髮送到Child.print()而不是Base.print()

Base類的構造函數運行怎麼來的JVM可以調用Child的方法,因爲Child'不創建對象s?

Base的構造函數運行,Child對象已經創建。但是,它並未完全初始化。這正是避免調用可以在構造函數中覆蓋的方法的原因:語言允許它,但程序員在做時要格外小心。

有關基類構造函數調用可覆蓋方法時可能發生的問題的更多信息,請參見this Q&A

+1

好點,創建vs初始化。之前我曾經對此感到困惑。 –

+0

@dasblinkenlight感謝您解決這個問題,並且鏈接很有用。 –

0

要執行的方法將根據類的實際對象

是這是正確的選擇。

Base base = new Child();

。它不會發生,你認爲它發生的方式while Base class constructor is running how come JVM can call Child's method since Child's object is not created?。 這裏發生的是,Child實例被創建,並且Child實例正在通過Child的默認構造函數創建,它首先調用超級構造函數that is where the 0 get printed