考虑以下代码示例,有人可以帮助解释为什么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 + ")";
}
}
答案 0 :(得分:2)
正如许多其他人同时指出的那样,属性在Java中被静态解析,而方法是动态解析的。这意味着属性 shadow ,而方法覆盖。将变量转换为超类(如隐式发生在this
指针上)不会影响方法的解析方式,但会改变属性的方式。
第二件事是即使 A
的示例中的构造函数要分配给B.x
,它也会在之前发生 B
- 构造对象的一部分(因为对象是从Object
的构造函数开始构造的,然后沿着类层次结构[1]向下走),B
的构造函数将覆盖它。您可以验证A
的构造函数是否看到未初始化的B
(仅用于学术目的),在this
的构造函数中向下转换A
指针并检查{{ 1}}。它将是0。
B.x
备注:强>
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.x
是x
中声明的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的值。
这有意义吗?