Java: 使用 super 调用时隐藏超类字段的值是多少?

Java: What's the value of a hidden superclass field when called using super?

考虑以下示例:

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

    public int howManyTires(){
        return tires; 
    }

    public void getColor(){
        getNiceColour();
    }

    public void getNiceColour(){
        System.out.println("Blue");
    }
}
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");
    }
}

输出为:

1
Magenta

我的问题是当通过super调用superclass'howManyTires函数时,this引用显然是subclass (如调用 getColor 方法所示)。然而,它 return superclass' tires 字段。

我知道字段只是隐藏而不是覆盖,但除非这些字段绑定到 class(如 class 变量),否则调用 superclass' howManyTires 方法应该 returned tiresthis 引用(属于子class)

绑定的值

I understand that fields are only hidden not overridden...

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

使用 public 字段和更明显的类型可能更容易看到:

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
    }
}

sSub 类型,bBase 类型。它们都引用同一个对象,但请注意用于访问字段的引用类型如何影响访问的字段。

字段是这样,方法是不是

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
    }
}