2011-08-02 197 views
14

在探索scjp問題時,我遇到了我發現很奇怪的行爲。Java繼承問題

我宣佈兩個類項目和博爾特如下:

class Item { 
    int cost = 20; 

    public int getCost() { 
     return cost; 
    } 
} 

class Bolt extends Item { 
    int cost = 10; 

    public int getCost() { 
     return cost; 
    } 
} 

,並試圖訪問成本的值的兩倍

public class Test { 
    public static void main(String[] args) { 
     Item obj = new Bolt(); 
     System.out.println(obj.cost); 
     System.out.println(obj.getCost()); 
    } 
} 

我得到的輸出是20 10 我可以」不明白這是怎麼發生的。

+0

否。@Override僅表示您希望此方法覆蓋另一個方法,並且如果不是這種情況,它應該會產生錯誤。但只要方法具有相同的簽名,第二個就會覆蓋第一個。 Java 5之前不存在註釋。 –

+0

@ netbrain,子類的getCost方法正常工作。我對直接調用obj.cost的結果很好奇。但正如Sanjay所說,這是由於運行時多態性僅適用於方法而不適用於字段。 –

回答

19

obj是因爲Itemcost字段的值Item類型因此第一20的基準爲20的第二個值是10由於obj運行時類型Bolt因此getCost()調用Bolt類的getCost(因爲Bolt延伸Item)。

簡而言之,運行時多態只適用於實例成員(方法重寫)而不適用於實例字段。

+1

是的。還有一個避免公共領域的理由。 –

+0

因此,Bolt對象中有兩個成本字段? – bcr

+0

從實現細節的角度來看,當你說'new Bolt()'時,只會創建* 1 *對象。但是,是的,該子類非常瞭解其超類宿主的字段/方法。你可以通過在你的代碼中添加第三個'sysout'來驗證它:'System.out.println(((Bolt)obj).cost)' –

7

類字段不參與多態性遊戲。這些方法可以。

因此,當您訪問該字段時,您將轉到基類中定義的字段,因爲對象的類型爲Item。當你調用方法時,你會得到實際值,因爲你使用多態性調用方法。

結論:

域總是私有。如果您想訪問字段寫入方法。

+0

這和Sanjay的回答對我來說很清楚。 –