Java继承问题

14

在寻找SCJP(Sun Certified Java Programmer)考试题目时,我遇到了这个我觉得奇怪的行为。

我声明了两个类Item和Bolt,如下所示:

class Item {
    int cost = 20;

    public int getCost() {
        return cost;
    }
}

class Bolt extends Item {
    int cost = 10;

    public int getCost() {
        return cost;
    }
}

并尝试两次访问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。我不明白为什么会这样。


No. @Override 只是向编译器指示你想要这个方法覆盖另一个方法,并且如果不是这样的话,它应该产生一个错误。但是一旦这两个方法具有相同的签名,第二个方法就会覆盖第一个方法。注解在 Java 5 之前不存在。 - JB Nizet
@netbrain,子类的getCost方法运行良好。我对直接调用obj.cost的结果很好奇。但正如Sanjay所说,这是因为运行时多态仅适用于方法而不是字段。 - santosh-patil
2个回答

19

obj 是一个 Item 类型的引用,因此第一个值为 20,因为 Item 类的 cost 字段的值为 20。第二个值是 10,因为 obj 的运行时类型是 Bolt,所以调用了 Bolt 类的 getCost() 方法(由于 Bolt 继承自 Item 类)。

简而言之,运行时多态只适用于实例成员(方法重写),而不适用于实例字段。


那么Bolt对象中有两个成本字段? - bcr
从实现细节的角度来看,当您说 new Bolt() 时,只创建了 一个 对象。但是,是的,子类基本上知道其超类托管的字段/方法。您可以通过在代码中添加第三个 sysout 来验证这一点: System.out.println(((Bolt)obj).cost) - Sanjay T. Sharma
@Sanjay,虽然我没有创建任何Item类的对象,但它仍然打印出了在Item类中定义的值。这就是我觉得奇怪的地方。 - santosh-patil

7

类字段不参与多态。方法才是。

因此,当您访问字段时,您会进入在基类中定义的字段,因为您对象的类型是 Item。当您调用方法时,使用多态来调用方法,从而获取实际值。

结论:

字段始终是私有的。如果要访问字段,请编写方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接