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

时间:2014-09-12 02:32:05

标签: java class inheritance constructor super

考虑以下代码示例,有人可以帮助解释为什么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 + ")";
   }
}

5 个答案:

答案 0 :(得分:2)

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

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

B.x

备注:

  1. 这可能看似不合逻辑:毕竟,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 } } 中的A的构造函数不是名为吗?事实证明B不是普通的方法调用,而是一个特殊的功能。

答案 1 :(得分:1)

您的班级B正在int x隐藏A。如果你不这样做,

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(正如您已经做过的那样)。

答案 2 :(得分:1)

  

我们使用A(int x){this x = x;}并且B的int x已经改为20.

实际上,没有。它尚未更改20。从来没有10

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

  • A (int x) { this.x = x; }中,this.xx中声明的A

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

当您分配给其中一个x变量时,它不会改变另一个变量。它们不同


这个问题/示例旨在说明的是 shadowing ...其中超类中的一个变量得到了#34;隐藏了#34;通过子类中的另一个变量。从设计/编码的角度来看,这是一个坏主意。您应该避免在真正的代码中执行此操作。

答案 3 :(得分:1)

原因是您有两个x个变量 - 一个在A中,另一个在B中,因此当您调用super(x)时,它会转到构造函数中A,因为它在A中,会将A x分配给super(x)的参数。因此,它将super.x设置为20,但不会更改x中的B。因此B s x停留在最初初始化为10的位置。

答案 4 :(得分:1)

B(int x,int y)构造函数具有与实例变量相同的参数名称,因此x传递给超级构造函数A将是传递给构造函数B的那个,并且它与实例变量x无关。实例变量x(定义为int x = 10;)值仅在由B的构造函数引用this.x时才会更改。 &#39;这&#39;用于表示调用该函数的对象的关键字。所以无论你传递B(任何值,y),它都会显示10作为输出,因为我们没有改变x的值。

这有意义吗?