[英]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
}
}
笔记:
B
的内部调用 A
的构造函数吗? 事实证明, super()
不是正常的方法调用,而是一种特殊功能。 您的班级B
正在使A
的int 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
,所以将A
的x
赋给了super(x)
参数。 因此,它将super.x
设置为20
,但不更改B
的x
。 因此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.