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.a
在 addFive()
中打印 8
。而 main()
中的 f.a
给出 3
。 this.
和 f.
引用的实例相同,但它们给出不同的结果。使用 this.a
给出 8
作为输出,这与我之前的理解相矛盾。
所以我的问题是,this.
是指 class 还是实例?我知道 this.
会引用调用方法的对象,但这个特定的程序让我感到困惑。
这里的关键字this
指的是调用该方法的当前对象实例。由于多态性,Bar
的 addFive
方法被调用。该方法引用那里范围内的 a
,即 Bar
的 a
。 (Bar
的 a
隐藏了 Foo
的 a
。)这就是最初打印 8
的原因,以及为什么它会更改为 13
。但是,当在 main
末尾调用 System.out.println(f.a);
时,编译器仅将 f
视为 Foo
变量,因此它打印 3
-- Foo
的 a
,从未从 3
.
改变
当在子类中声明一个与超类同名的变量时,您隐藏了变量,这与被覆盖的方法不同。这种区别是因为 f 指向一个 Bar 类型的对象,所以使用了 Bar 中的 addFive() 方法。然而,当调用 f.a 时,它的引用类型是 Foo 并且它首先在那里寻找变量。因此,通常应避免在子类中隐藏变量。
关于运行这个代码
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.a
在 addFive()
中打印 8
。而 main()
中的 f.a
给出 3
。 this.
和 f.
引用的实例相同,但它们给出不同的结果。使用 this.a
给出 8
作为输出,这与我之前的理解相矛盾。
所以我的问题是,this.
是指 class 还是实例?我知道 this.
会引用调用方法的对象,但这个特定的程序让我感到困惑。
这里的关键字this
指的是调用该方法的当前对象实例。由于多态性,Bar
的 addFive
方法被调用。该方法引用那里范围内的 a
,即 Bar
的 a
。 (Bar
的 a
隐藏了 Foo
的 a
。)这就是最初打印 8
的原因,以及为什么它会更改为 13
。但是,当在 main
末尾调用 System.out.println(f.a);
时,编译器仅将 f
视为 Foo
变量,因此它打印 3
-- Foo
的 a
,从未从 3
.
当在子类中声明一个与超类同名的变量时,您隐藏了变量,这与被覆盖的方法不同。这种区别是因为 f 指向一个 Bar 类型的对象,所以使用了 Bar 中的 addFive() 方法。然而,当调用 f.a 时,它的引用类型是 Foo 并且它首先在那里寻找变量。因此,通常应避免在子类中隐藏变量。