2011-08-02 170 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的回答对我来说很清楚。 –