Java 继承混乱,超类和子类成员变量同名

Java inheritance confusion, superclass and subclass member variable having same name

关于运行这个代码

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。所以我猜想一个带有 superclass 引用变量的 subclass 对象使用 superclass 变量,以防两个 classes.[=30= 中的同名变量]

但是,运行这个程序来自 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

main() 中调用的 addFive() 方法将是 class Bar 的方法,因为覆盖了。

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

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

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

改变

当在子类中声明一个与超类同名的变量时,您隐藏了变量,这与被覆盖的方法不同。这种区别是因为 f 指向一个 Bar 类型的对象,所以使用了 Bar 中的 addFive() 方法。然而,当调用 f.a 时,它的引用类型是 Foo 并且它首先在那里寻找变量。因此,通常应避免在子类中隐藏变量。