繁体   English   中英

子类中的超级构造函数-Java

[英]Super constructor in a subclass - Java

考虑下面的代码示例,有人可以帮助解释为什么B b3= new B (20, 50) ; System.out.println(b3) ; A:20, B:(10, 61)吗? 我以为通过调用super (x) ,我们使用A(int x) {this x =x;} ,B的int x已更改为20。

PS:我正在寻找其工作原理的原因,而不是如何在B中打印出一定的值。

class A {
  int x;
  A(int x) {
    this.x = x; 
  }
  public String toString() {
     return "A:" + x;
  } 
}
 class B extends A {
   int x = 10;
   int y = x+1;

   B(int x, int y) {
     super(x);
     this.y = this.y + y;
   }
   public String toString() {
     return "A:" + super.x + ", B:(" + x + "," + y + ")";
   }
}

正如许多其他人同时指出的那样, 属性是在Java中静态解析的,而方法是动态解析的。 这意味着方法覆盖时属性阴影 将变量强制转换到其超类(隐式发生在this指针上)不会影响方法的解析方式,但会改变属性的方式。

第二件事是, 即使您示例中的A的构造函数分配给Bx ,它也会在对象的B部分被构造之前发生(因为对象是从Object的构造函数开始构造的,然后向下走该类层次结构[1]), B的构造函数将覆盖它。 您可以验证A的构造函数是否看到未初始化的B是(仅出于学术目的)在A的构造函数中this指针向下转换并检查Bx 它将是0。

class A {
    int x;
    A(int x) {
        System.out.printf("A() before: A.x = %d%n", this.x);  // 0
        System.out.printf("A() before: B.x = %d%n", (B) this).x);  // 0
        this.x = x;
        System.out.printf("A() after: A.x = %d%n", this.x);  // 7
        System.out.printf("A() after: B.x = %d%n", (B) this).x);  // 0
    }
}

class B extends A {
    int x = 10;
    B() {
        super(7);
        System.out.printf("B(): A.x = %d%n", super.x);  // 7
        System.out.printf("B(): A.x = %d%n", this.x);  // 10
    }
}

笔记:

  1. 这似乎是不合逻辑的:毕竟,不是从B的内部调用 A的构造函数吗? 事实证明, super()不是正常的方法调用,而是一种特殊功能。

您的班级B正在使Aint x蒙上阴影。 如果你不这样做

class B extends A {
  // int x = 10; // <-- shadows A.x
  int y = x+1;

  B(int x, int y) {
    super(x);
    this.y = this.y + y;
  }
  public String toString() {
    return "A:" + super.x + ", B:(" + x + "," + y + ")";
  }
}

然后您的代码将按预期工作。 您的影子意味着实际上有两个名为x变量。 要获得父代,您需要super.x (就像您已经做的那样)。

我们使用A(int x){this x = x;},B的int x已更改为20。

其实没有 尚未更改20 从来没有10

有两个单独的x实例变量,一个在A声明,一个在B

  • A (int x) { this.x = x; } A (int x) { this.x = x; }this.x是在A声明的x

  • class B extends A { int x = 10; ... class B extends A { int x = 10; ... x是另外一个。

当您分配给x变量之一时,它不会更改另一个变量。 它们是截然不同的


这个问题/示例旨在说明的问题是阴影 ...超类中的一个变量被子类中的另一个变量“隐藏”。 从设计/编码的角度来看,这是一个坏主意。 您应该避免在真实代码中这样做。

原因是您有两个x变量-一个在A ,一个在B ,因此,当您调用super(x) ,它将转到A的构造函数,因为它在A ,所以将Ax赋给了super(x)参数。 因此,它将super.x设置为20 ,但不更改Bx 因此B s x停留在最初初始化为的10处。

B(int x,int y)构造函数的名称与实例变量相同,因此传递给超级构造函数A的x将成为传递给构造函数B的变量,并且与实例变量x不相关。 实例变量x(定义为int x = 10;)的值只有在B的构造函数中由this.x引用时才会更改。 “ this”关键字用于引用调用该函数的对象。 因此,无论您传递什么B(任何值y),由于我们不更改x的值,它将为x显示10作为输出。

这有意义吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM