运行此代码
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()
给出3
。 this.
和f.
引用的实例相同,但它们会给出不同的结果。使用this.a
会将8
作为输出,这与我之前的理解相矛盾。
所以我的问题是,this.
是指某个类还是实例?我知道this.
会引用调用方法的对象,但是这个特定的程序让我很困惑。
答案 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,它首先在那里查找变量。出于这个原因,通常应该避免在子类中隐藏变量。