Java继承了方法问题

时间:2009-12-15 15:32:48

标签: java inheritance scjp

在参加SCJP 6考试时,我在考试中遇到了这个问题:

class A{  
    private static String staticProperty = " a ";  
    String getStaticProperty() { return staticProperty; }  
}  

class B extends A {  
    private static String staticProperty = " b ";  
    public static void main(String[] args){  
        new B().go(new A());  

    }  
    void go(A t){  
        String s = t.getStaticProperty() + B.staticProperty + staticProperty + (new B().getStaticProperty());  
        System.out.println(s);  
    }  
}  

输出是什么?

此处的输出为a b b a

我完全理解a b b,但最后并不理解“a”。如果你继承了一个方法(在这种情况下,B从A继承getStaticProperty()),并且该方法返回一个来自父(staticProperty)的静态变量,你在子节点中重新定义,你将总是使用父静态变量值??

顺便说一下,删除静态标识符并使​​staticField成为类的实例成员会返回相同的结果。修改从私有到公共或其他的访问修饰符返回相同的结果。我需要覆盖getStaticProperty方法以获得我想要看到的内容。

5 个答案:

答案 0 :(得分:4)

字段访问不受dynamic dispatch方法访问的约束,即字段无法覆盖。 A类中的这一行:

String getStaticProperty() { return staticProperty; }  

因此引用了A类中的字段staticProperty。具有相同名称的B类字段无关紧要,或者更确切地说:隐藏超类字段,而B类中的所有代码都将使用此字段。 Sun's Java tutorial就此事提出了这个问题:

  

在一个类中,一个具有该字段的字段   与超类中的字段同名   隐藏超类的字段,即使   他们的类型不同。内   子类,超类中的字段   不能简单引用   名称。相反,该领域必须   通过super访问,这是   将在下一节中介绍。通常   说起来,我们不建议隐藏   字段,因为它使代码很难   读取。

答案 1 :(得分:3)

new B().getStaticProperty()正在调用A中的方法,该方法返回A的静态属性,因为它的作用域为A

答案 2 :(得分:1)

函数在Java中是虚拟的,但类成员(静态或实例)不是。因此,虽然B对staticProperty的定义可能会掩盖A的定义,但它不会覆盖它。

// in B
String fromChild = staticProperty; // == "b"
String fromParent = A.staticProperty; // == "a", was masked but not overridden

让A访问B中定义的变量的唯一方法是在A中定义一个getter函数,并按照你的建议在B中覆盖它。

答案 3 :(得分:1)

在考虑诸如此类的继承问题时,您可能会发现在调用new B()时会发生什么变得有帮助。当B的构造函数执行时,它执行的第一个操作(因为没有对A的构造函数的显式调用)是super()。此时创建了A的实例,在此对象中,getStaticProperty()方法明确指的是A的staticProperty。 B的构造函数的主体然后运行(再次,只有在成功执行A的构造函数之后),并且因为它没有做任何改变或覆盖由A的构造函数实例化的getStaticProperty()方法,它当然不会改变行为那个方法要么。

这最初可能看起来令人困惑,但它可以是一种有用的方式来思考各种继承问题的含义。

答案 4 :(得分:0)

getStaticProperty()是在类A上定义的方法。该方法未在类B上重写,因此使用了类A中的方法。由于A不能以任何方式“看到”B的静态属性,因此它返回它自己的值。

相关问题