Java继承混淆,超类和子类成员变量具有相同的名称

时间:2015-06-05 18:48:10

标签: java inheritance this

运行此代码

class c1 { int ci = 1; }

class c2 extends c1 { int ci = 2; }

class inheritanceTest {
    public static void main(String args[]) {
        c1 c1reftoc2 = new c2();
        System.out.println(c1reftoc2.ci);
    }
}

输出为1。所以我猜这个带有超类引用变量的子类对象,如果两个类中的同名变量都使用超类变量。

但是,从SCJP问题运行该程序,

class Foo {
    public int a = 3;
    public void addFive() {
        a += 5;
        System.out.print("f ");
    }
}

class Bar extends Foo {
    public int a = 8;
    public void addFive() {
        System.out.println(this.a);
        this.a += 5;
        System.out.print("b " );
        System.out.println(this.a);
    }
}

class SCJPQC3 {
    public static void main(String[] args) {
        Foo f = new Bar();
        f.addFive();
        System.out.println(f.a);
    }
}

输出

8
b 13
3

由于覆盖,addFive()中调用的main()方法将属于类Bar

this.a中的

addFive()打印8。而f.a中的main()给出3this.f.引用的实例相同,但它们会给出不同的结果。使用this.a会将8作为输出,这与我之前的理解相矛盾。

所以我的问题是,this.是指某个类还是实例?我知道this.会引用调用方法的对象,但是这个特定的程序让我很困惑。

2 个答案:

答案 0 :(得分:3)

此处的关键字this指的是调用该方法的当前对象实例。由于多态性,调用了Bar的{​​{1}}方法。该方法引用了addFive范围内的a,即Bar的{​​{1}}。 (a的{​​{1}} 隐藏了 Bar的{​​{1}}。)这就是为什么a最初打印的原因,以及为什么变为Foo。但是,在a末尾调用8时,编译器只会将13视为System.out.println(f.a);变量,因此会打印main - {{ 1}}的{​​{1}},从未从f更改。

答案 1 :(得分:1)

在子类中声明一个与超类中名称相同的变量时,隐藏变量,与被覆盖的方法不同。这种差异是因为f指向Bar类型的对象,所以使用Bar中的addFive()方法。但是,当调用f.a时,它的引用类型是Foo,它首先在那里查找变量。出于这个原因,通常应该避免在子类中隐藏变量。