这个简单的java程序的结果?

时间:2013-04-14 03:27:42

标签: 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 = 123;

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

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

现在在我的主要班级

    NotActuallyImmutable n = new Mutable(42); // line2
    int x = n.getX();
    System.out.println("x is"+x);

我期待输出为42,但它将输出返回为123.我期待42,因为在第2行我正在创建类Mutable的对象然后在第1行我将值设置为42.所以当我这样做时{ {1}}我应该得到这个最新的值而不是默认的123.我知道我错过了一些但却无法弄清楚其背后的逻辑吗?

5 个答案:

答案 0 :(得分:2)

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

请注意,如果您从NotActuallyImmutable.x中删除了实例字段,则会出现编译错误,因为NotActuallyImmutableMutable是私有的,NotActuallyImmutable.x中的任何代码都无法访问}。

如果您将Mutable.x设为受保护字段,那么Mutable.x会影响它,您仍然会有相同的行为。如果您在这种情况下删除了final,那么您仍然会遇到编译错误,因为您尝试增加Mutable.getX()字段。

如果您删除x,那么getX()将返回的NotActuallyImmutable.x将为Mutable,尽管{{1}中有另一个同名字段}}

答案 1 :(得分:2)

private int x中的Mutableprivate int x中的NotActuallyImmutable是完全不同的字段,只有相同的名称。

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

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

答案 2 :(得分:1)

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

这意味着您有一个NotActuallyImmutable类型的对象,但创建的对象的实例是Mutable。 所以在这段代码中你处理Mutable对象将返回123.因为你传递的数字保存在NotActuallyImmutable中而不是Mutable中,

答案 3 :(得分:0)

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

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

创建新的Mutable。执行parent(x),将父类的x设置为42。

int x = n.getX();

nMutable个实例,因此会调用Mutable的{​​{1}},其中getX()的值为Mutable(123)而不是父母的。

答案 4 :(得分:0)

我同意上述答案中给出的尼斯解释。但要简要介绍最后的理解。当我正在做新的Mutable(42).getX()时,jvm首先会查看Mutable对象,以获取不在NotActuallyImmutable内的X值。如果我从Mutable中删除了getX()方法,我得到了预期的(按照我的期望)值,即42。

此示例变得混乱becoz变量名称,即父和子类中的X相同但有助于理解概念