这个简单java程序的结果是什么?

这个简单java程序的结果是什么?,java,inheritance,Java,Inheritance,现在在我的主课上 public class NotActuallyImmutable { private final int x; public NotActuallyImmutable(int x) { this.x = x;// line 1 } public int getX() { return x; } } public class Mutable extends NotActuallyImmutable { private int x

现在在我的主课上

public class NotActuallyImmutable {
  private final int x;

  public NotActuallyImmutable(int x) {
    this.x = x;// line 1
  }

  public int getX() {
    return x;
  }
}


public class Mutable extends NotActuallyImmutable {
  private int x = 123;

  public Mutable(int x) {
    super(x);
  }

  public int getX() {
    return x++;
  }
}

我期望输出为42,但它返回的输出为123。我期望42,因为在第2行,我使类的对象可变,然后在第1行,我将值设置为42。因此,当我执行
n.getX()
时,我应该得到这个最新值,而不是默认值123。我知道我遗漏了一些东西,但无法理解其背后的逻辑?

问题是
Mutable
中的
x
字段和class
notallyimmutable
中的
x
字段不一样。由
getX()
返回的
x
Mutable
中的一个(因为调用的
getX()
Mutable.getX()
,而不是
NotActuallyImmutable.getX()

请注意,如果从
Mutable
中删除实例字段,则会出现编译器错误,因为
NotActuallyImmutable.x
NotActuallyImmutable
的私有字段,并且
Mutable
中的任何代码都无法访问

如果将
NotActuallyImmutable.x
设置为受保护的字段,则
Mutable.x
将对其进行阴影处理,并且您仍然具有相同的行为。如果在本例中删除了
Mutable.x
,仍然会出现编译器错误,因为您试图递增
final
字段


如果删除
Mutable.getX()
,则
getX()
返回的
x
将是
NotActuallyImmutable.x
,尽管在
Mutable
中有另一个同名字段,但
Mutable
中的
private int x
notactualyimmutable
中的
private int x
是完全不同的字段,它们只有相同的名称

这对编译器来说不是问题,因为您无法从另一个类访问
private
字段。因此,就编译器而言,当您定义
Mutable
时,
NotActuallyImmutable
中的
x
是不可见的,也可能不存在

这当然会让程序员感到困惑。如果将其中一个字段重命名为
y
(将getter方法重命名为
getY
),则行为看起来更直观

    NotActuallyImmutable n = new Mutable(42); // line2
    int x = n.getX();
    System.out.println("x is"+x);
这意味着您有一个NotActuallyImmutable类型的对象,但所创建对象的实例是可变的。
因此,在这段代码中,您将处理将返回123的可变对象。由于您传递的数字保存为NotActualYimmutable而非Mutable,

n
有两个不同的
x
值,它们在不同的上下文中可见,即父类的私有成员变量和子类的私有成员变量

NotActuallyImmutable n = new Mutable(42); // line2
创建新的
可变
。执行将父类的
x
设置为42的
parent(x)

NotActuallyImmutable n = new Mutable(42); // line2

n
是一个
Mutable
实例,因此调用
Mutable
getX()
,它返回
Mutable
(123)的值,而不是父对象的值。

我同意上面答案中给出的很好的解释。只是简单介绍一下最后的理解。在我执行新的Mutable(42).getX()时,jvm将首先查找Mutable对象,以获取NotActuallyImmutable中没有的X值。如果我从Mutable中删除getX()方法,我会得到预期的值,即42


这个例子很混乱,因为变量名,即X在父类和子类中是相同的,但有助于理解概念

您确定可以编译上面的代码吗?在这种情况下,我不会使用术语“阴影”。对我来说,“阴影”意味着如果第二个变量不存在,第一个变量可以访问,但在这种情况下,即使第二个变量不存在,你也无法访问第一个
x
。@SamuelEdwinWard-是的,我在修复语言时看到你的注释弹出。
int x = n.getX();