实例字段的继承在此特定代码中如何工作?

2022-09-01 00:14:52
class A
{
    int a = 2, b = 3;
    public void display()
    {
        int c = a + b;
        System.out.println(c);
    }
}
class B extends A
{
    int a = 5, b = 6;
}
class Tester
{
    public static void main(String arr[])
    {
        A x = new A();
        B y = new B();
        x.display();
        y.display();
    }
}

为什么输出显示为 5,5?而不是5,11?。该方法如何工作?y.display()


答案 1

为什么输出是5,5?

因为只知道字段和 .这些是任何代码都知道的唯一字段。看起来您希望 中的声明“覆盖”现有的字段声明。他们没有。它们声明隐藏现有字段的新字段。变量的行为方式与方法不同 - 重写变量的概念根本不存在。来自 JLS 第 8.3 节A.display()A.aA.bAB

如果类声明具有特定名称的字段,则该字段的声明称为隐藏超类和类的超接口中具有相同名称的字段的任何和所有可访问声明。

您可以通过更改其构造函数来更改它从中继承的现有字段的值来获得所需的效果:BA

class B extends A {
    B() {
        a = 5;
        b = 6;
    }
}

请注意,这些不是变量声明。它们只是作业。当然,在大多数代码中(好吧,无论如何我见过的大多数代码),中的字段将是私有的,因此无法从 访问,但这只是用于解释语言行为的示例。AB


答案 2

在类中,您声明字段和 .该方法使用这些字段。在类中,您声明同名的新字段。您实际上是在隐藏旧字段,而不是“覆盖”它们。要为相同的字段分配不同的值,请使用构造函数:AabdisplayB

class A {
    A(int a, int b) {
        this.a = a;
        this.b = b;
    }

    A() {
        this(2, 3);
    }

    int a,b;

    public void display() {
        int c=a+b;
        System.out.println(c);
    }
}

class B extends A {
    B() {
        super(5, 6);
    }
}

推荐