Java:使用超级调用时,隐藏的超类字段的值是什么?

Dau*_*aud 2 java oop inheritance overriding

考虑以下示例:

public class Main
{
    public static void main(String[] args) {
        System.out.println(new Maruti().howManyTires());
        new Maruti().getColor();
    }
}
Run Code Online (Sandbox Code Playgroud)
class Car {
    private int tires = 1;

    public int howManyTires(){
        return tires; 
    }

    public void getColor(){
        getNiceColour();
    }

    public void getNiceColour(){
        System.out.println("Blue");
    }
}
Run Code Online (Sandbox Code Playgroud)
class Maruti extends Car {

    private int tires = 10;

    public int howManyTires(){
        return super.howManyTires();
    }

    public void getColor(){
        super.getColor();
    }

    public void getNiceColour(){
        System.out.println("Magenta");
    }
}
Run Code Online (Sandbox Code Playgroud)

输出为:

1
Magenta
Run Code Online (Sandbox Code Playgroud)

我的问题是,当howManyTires通过调用超类的函数时superthis引用显然是子类的(如对getColor方法的调用所示)。然而,它返回了超类的tires领域。

我知道字段仅被隐藏而不被覆盖,但是除非这些字段绑定到类(如类变量),否则调用超类的howManyTires方法应该返回tiresthis引用(属于子类)绑定的值。

T.J*_*der 5

我了解字段仅被隐藏而不被覆盖...

究竟。tires由创建的对象中有两个字段new Maruti,的tires字段Car和的tires字段Maruti。您访问哪一个取决于您用于访问该对象的引用的类型。的类型的this由类的方法来确定是:this内的Maruti方法具有的类型Maruti; this一个内Car方法具有类型Car。这就是为什么MarutihowManyTires访问Maruti tires,和CarhowManyTires访问Cartires,即使在两种情况下,对象this是指一个Maruti对象。

对于公共字段和更明显的类型,这可能更容易看到:

class Base {
    public int a = 1;
}

class Sub extends Base {
    public int a = 2;
}

public class Main {
    public static void main(String[] args) {        
        Sub s = new Sub();
        Base b = s;
        System.out.println(s.a); // 2
        System.out.println(b.a); // 1
    }
}
Run Code Online (Sandbox Code Playgroud)

s是类型Subb是类型Base。它们都引用同一对象,但是请注意用于访问该字段的引用的类型如何影响访问哪个字段。

对于字段而不是方法,这是正确的:

class Base {
    public int a = 1;
    public int method() {
        return 1;
    }
}

class Sub extends Base {
    public int a = 2;
    public int method() {
        return 2;
    }
}

public class Main {
    public static void main(String[] args) {        
        Sub s = new Sub();
        Base b = s;
        System.out.println(s.a);        // 2
        System.out.println(b.a);        // 1
        System.out.println(s.method()); // 2
        System.out.println(b.method()); // 2
    }
}
Run Code Online (Sandbox Code Playgroud)