繁体   English   中英

解释变量隐藏在这个Java代码中是如何工作的

[英]Explain how variable hiding is working in this Java code

考虑下面的代码

class A
{
    int x = 5;
    void foo()
    {
        System.out.println(this.x);
    }
}
class B extends A
{
    int x = 6;
    // some extra stuff
}
class C
{
    public static void main(String args[])
    {
         B b = new B();
         System.out.println(b.x);
         System.out.println(((A)b).x);
         b.foo();
    }
 }  

该计划的输出是

6
5
5

我理解前两个但是无法理解最后一个。 b.foo()如何打印5.B类将继承foo方法。 但它不应该打印bx会打印什么? 到底发生了什么?

是的, B类继承了foo方法。 但是B的变量x隐藏了Ax ; 它不会取代它。

这是一个范围问题。 Afoo方法只能看到范围内的变量。 范围中唯一的变量是A的实例变量x

foo方法在B继承但未被覆盖。 如果您使用相同的确切代码显式覆盖foo

class B extends A
{
    int x = 6;

    @Override
    void foo()
    {
        System.out.println(this.x);
    }
}

然后该变量时提到了,这将是在范围this.xBx ,和6将被打印。 虽然方法的文本是相同的,但由于范围的原因,引用是不同的。

顺便提一下,如果你真的想在B类中引用Ax ,你可以使用super.x

字段在Java和具有相同字段名称的子类中不能覆盖父类阴影“仅”父类的字段。
所以this.x指的是当前类中定义的xA
结果: 5

更确切地说: foo()方法由B子类继承,但它并不意味着继承方法的行为将因引用的实例字段而改变,因为所述字段不可覆盖:引用的this.x表达式foo()方法中的Ax字段继续引用Ax

这与之前的两个陈述完全相同:

 B b = new B();
 System.out.println(b.x); // refers B.x -> 6
 System.out.println(((A)b).x); // refers A.x -> 5
 b.foo(); // refers under the hood A.x -> 5

rgettman的非常好的答案显示了如何克服隐藏在子类中的字段。
克服隐藏的替代方法依赖于使实例字段为private (建议使用)并提供返回值的方法。
通过这种方式,您可以从覆盖机制中受益,并且字段隐藏不再是类的客户端的问题:

class A
{
    private int x = 5;

    int getX(){
        return x;
    }

    void foo()
    {
        System.out.println(this.getX());
    }
}
class B extends A
{
    private int x = 6;

    int getX(){
        return x;
    }
}

嗯,这是因为静态绑定。

1)Java中的静态绑定在编译时发生,而动态绑定在运行时发生。

2)私有方法,最终方法和静态方法和变量使用静态绑定并由编译器绑定,而虚拟方法在运行时基于运行时对象绑定。

3)静态绑定使用Type(Java中的类)信息进行绑定,而动态绑定使用Object来解析绑定。

4)使用静态绑定绑定重载方法,而在运行时使用动态绑定绑定重写方法。

JAVA中 ,可以覆盖方法,而变量则不能。 因此,由于您的方法foo未在B被覆盖,因此它从A获取成员变量。

你打电话的时候

b.foo(); 

它检查B是否覆盖了方法foo() ,它没有。 然后它向一个级别向上看,超类A并调用该方法。

然后你调用了Afoo()版本然后打印出来

this.x

现在, A看不到Bx版本。


为了解决这个问题,你必须覆盖B的方法

class B extends A
{
    int x = 6;

    @Override
    void foo()
    {
        System.out.println(this.x);
    }

}

现在,打电话

b.foo();

将调用Bfoo()版本,您将获得预期的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM