5

我在网上搜索了类似的问题,但找不到。所以,在这里发帖。

在下面的程序中,为什么“i”的值被打印为 100?

AFAIK 'this' 指的是当前对象;在这种情况下是“TestChild”,并且类名也正确打印。但是为什么实例变量的值不是200呢?

public class TestParentChild {
    public static void main(String[] args) {
        new TestChild().printName();
    }
}

class TestChild extends TestParent{
    public int i = 200;
}

class TestParent{
    public int i = 100;
    public void printName(){
        System.err.println(this.getClass().getName());
        System.err.println(this.i); //Shouldn't this print 200
    }
}

此外,以下输出与我预期的一样。当我从父类调用“ this.test() ”时,调用子类方法。

public class TestParentChild {
    public static void main(String[] args) {
        new TestChild().printName();
    }
}

class TestChild extends TestParent{
    public int i = 200;
    public void test(){
        System.err.println("Child Class : "+i);
    }

}

class TestParent{
    public int i = 100;
    public void printName(){
        System.err.println(this.getClass().getName());
        System.err.println(this.i); //Shouldn't this print 200
        this.test();
    }
    public void test(){
        System.err.println("Parent Class : "+i);
    }
}
4

3 回答 3

7

Java 没有虚拟字段,所以i字段printName总是指TestParent.i代而不是任何后代子代。

Java中通过继承实现的多态性只发生在方法上,所以如果你想要你描述的行为,那么你会想要这个:

class TestChild extends TestParent{

    private int i = 200;

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

class TestParent{

    private int i = 100;

    public int getI() { return this.i; }

    public void printName(){
        System.err.println( this.getClass().getName() );
        System.err.println( this.getI() ); // this will print 200
    }
}
于 2012-12-31T05:11:54.357 回答
2

因为 Java 中的字段不是继承的。使用您的声明,您已经有效地声明了两个名为 的不同字段i,并且 的实例TestChild将同时拥有这两个字段。TestParent编译时,其方法中的引用将i始终引用TestParent.i.

于 2012-12-31T05:13:12.643 回答
2

没有办法覆盖类变量。

您不会覆盖 Java 中的类变量,而是隐藏它们。覆盖是实例方法,隐藏不同于覆盖。

在您给出的示例中,通过在类中声明名为“i”TestChild的类变量,您隐藏了它将从其超类继承的TestParent具有相同名称“i”的类变量。以这种方式隐藏变量不会影响超类中类变量“i”的值TestParent

要获得所需的行为,您只需覆盖该getI()方法

class TestChild extends TestParent{

    private int i = 200;

    @Override
    public int getI() {
         return this.i;
    }
}
于 2012-12-31T05:17:37.640 回答