Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java继承混乱,超类和子类成员变量同名_Java_Inheritance_This - Fatal编程技术网

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

Java继承混乱,超类和子类成员变量同名,java,inheritance,this,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。所以我猜一个带有超类引用变量的子类对象,在

在运行此代码时

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
由于重写,在
main()
中调用的
addFive()
方法将是类
Bar
的方法

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


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

这里的关键字
this
指调用方法的当前对象实例。由于多态性,调用了
Bar
addFive
方法。该方法引用了那里范围内的
a
,即
Bar
a
。(
Bar
's
a
隐藏
Foo
's
a
)这就是为什么最初打印
8
,并将其更改为
13
。然而,当
System.out.println(f.a)
main
的末尾被调用,编译器只将
f
视为
Foo
变量,因此它打印
3
--
Foo
a
,它从未从
3
更改。这里的关键字
this
指调用该方法的当前对象实例。由于多态性,调用了
Bar
addFive
方法。该方法引用了那里范围内的
a
,即
Bar
a
。(
Bar
's
a
隐藏
Foo
's
a
)这就是为什么最初打印
8
,并将其更改为
13
。然而,当
System.out.println(f.a)
main
的末尾被调用,编译器只将
f
视为
Foo
变量,因此它打印
3
--
Foo
a
,该变量从未从
3

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

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

您需要记住一条简单的规则:字段不是多态的,只有方法是多态的。如果
this
位于
SomeClass
的代码块中,您可以将其视为
SomeClass this
引用(尽管它是关键字)。@Pshemo确实消除了一些混淆:)您需要记住一条简单的规则:字段不是多态的,只有方法是多态的。如果
this
SomeClass
的代码块中,您可以将其视为
SomeClass this
引用(尽管它是关键字)。@Pshemo确实消除了一些混淆:)谢谢,我读过关于隐藏变量的内容,但不知道它在方法中的应用。构造函数中也会发生同样的情况吗?谢谢,我读过关于隐藏变量的内容,但不知道它在方法中的应用。在构造函数中也会发生同样的情况吗?