Java继承中的字段隐藏

17

在一个类中,与父类中同名的字段会隐藏掉父类的字段。

public class Test {

    public static void main(String[] args) {

        Father father = new Son();
        System.out.println(father.i); //why 1?
        System.out.println(father.getI());  //2
        System.out.println(father.j);  //why 10?
        System.out.println(father.getJ()); //why 10?

        System.out.println();

        Son son = new Son();
        System.out.println(son.i);  //2 
        System.out.println(son.getI()); //2
        System.out.println(son.j); //20
        System.out.println(son.getJ()); //why 10?
    }  
}

class Son extends Father {

    int i = 2;
    int j = 20;

    @Override
    public int getI() {
        return i;
    }
}

class Father {

    int i = 1;
    int j = 10;

    public int getI() {
        return i;
    }

    public int getJ() {
        return j;
    }
}

有人能为我解释一下结果吗?


1
有关隐藏变量的Oracle教程 - alex
2
儿子不是父亲的一种类型。 - jsj
3
我不明白为什么这个问题会被认为是“过于局限”... :D - Willi Mentzel
1
@WilliMentzel 我也一样,这正是我在寻找的。 - NickL
2个回答

16
在Java中,字段不具有多态性。
Father father = new Son();
System.out.println(father.i); //why 1? Ans : reference is of type father, so 1 (fields are not polymorphic)
System.out.println(father.getI());  //2 : overridden method called
System.out.println(father.j);  //why 10? Ans : reference is of type father, so 2
System.out.println(father.getJ()); //why 10? there is not overridden getJ() method in Son class, so father.getJ() is called

System.out.println();

// same explanation as above for following 
Son son = new Son();
System.out.println(son.i);  //2 
System.out.println(son.getI()); //2
System.out.println(son.j); //20
System.out.println(son.getJ()); //why 10?

2
仅限于Java吗?还有其他语言可以在字段上提供多态性吗? - Asif Mushtaq

4
根据覆盖和隐藏方法
引用超类时调用被子类覆盖的方法将调用超类方法并访问超类成员变量,具体取决于该方法是从超类还是子类调用。这解释了以下内容:
System.out.println(father.i);  //why 1?
System.out.println(father.j);  //why 10?
System.out.println(father.getJ()); //why 10?

同样适用于以下内容:
System.out.println(son.getJ()); //why 10?

由于Son中未定义getJ(),因此调用了Father版本,该版本看到了在Father类中定义的成员。

如果您阅读隐藏字段;他们明确不推荐这种编码方法,因为

一般来说,我们不建议隐藏字段,因为它使代码难以阅读。


非常抱歉,但这是不真实的。原始来源被错误引用了。你的引用是指特别的static方法,而不是一般方法。请注意下面的原始来源措辞。(1)“调用被重写的实例方法的版本是子类中的方法。”(2)“调用隐藏的静态方法的版本取决于它是从超类还是从子类中调用的。” - Grateful
因此,实质上,如果您通过超类引用调用在子类中被覆盖的方法,则会调用SUBCLASS方法版本...而不是您所暗示的超类方法。 - Grateful

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