英文:
Inner class object
问题
我无法理解下面代码的行为。
我原本的期望是两个 `println()` 方法都应该打印出 100。为什么结果会不同呢?
如果我取消注释内部类中的 `getX()` 方法,那么两个 `println()` 方法的输出就会相同,都是 100。
我无法理解这种不同行为的原因。请帮我理解。
public class Foo {
public static void main(String[] args) {
MyOuter outerObj = new MyOuter();
MyOuter.MyInner innerObj = outerObj.new MyInner();
innerObj.setX();
System.out.println("x: " + innerObj.getX()); //x: 3
System.out.println("x: " + outerObj.getX()); //x: 100
}
}
class MyOuter {
private int x = 3;
public int getX() { return x; }
class MyInner extends MyOuter {
public void setX(){ x = 100; }
// public int getX() { return x; }
}
}
<details>
<summary>英文:</summary>
I couldn't understand the behavior of the below code.
My expectation was that it should print 100 in both `println()` methods. Why the result is different?
If I uncomment `getX()` method in inner class, then the output of `println(`) methods are the same which is 100.
I couldn't figure out the reasoning of different behavior. Please help me to understand.
public class Foo {
public static void main(String[] args) {
MyOuter outerObj = new MyOuter();
MyOuter.MyInner innerObj = outerObj.new MyInner();
innerObj.setX();
System.out.println("x: " + innerObj.getX()); //x: 3
System.out.println("x: " + outerObj.getX()); //x: 100
}
}
class MyOuter {
private int x = 3;
public int getX() { return x; }
class MyInner extends MyOuter {
public void setX(){ x = 100; }
// public int getX() { return x; }
}
}
答案1
得分: 4
从MyInner
的角度来看,这里涉及两个private int x
字段:
- 一个字段是从
MyOuter
继承而来的super.x
,但由于被声明为private
,因此不可访问。作为继承对象的MyInner
无法访问此字段。 - 另一个字段是来自周围的
MyOuter
实例的MyOuter.this.x
(因为MyInner
是一个(非静态)内部类,它始终绑定到周围MyOuter
的实例),是可访问的。
在MyInner
中的setX()
方法无法访问继承的字段super.x
,因此它访问字段MyOuter.this.x
并将其值设置为100
。对周围MyOuter
的连续调用getX()
将返回100
。
调用innerObj.getX()
(从MyOuter
继承而来,可以访问super.x
)将返回继承字段super.x
的值(仍然保持其初始值为3
)。
如果我们从MyInner
中删除extends MyOuter
并在其中包括getX()
方法,则代码将按预期行为运行。
MyInner
无法访问继承的private x
字段的事实一开始可能令人困惑,但实际上,这种行为与继承类中静态方法上下文中关键字protected
的行为一致,如Hariharan的这篇帖子中所讨论的。
英文:
From MyInner
's perspective, there are two private int x
fields in play here:
- One field
super.x
that is inherited fromMyOuter
, but inaccessible because it is declared asprivate
, andMyInner
as an inheriting object cannot access this field. - One field
MyOuter.this.x
from the sorroundingMyOuter
-instance (sinceMyInner
is a (non-static) inner class, it is always bound to an instance of the surroundingMyOuter
), that is accessible.
The method setX()
in MyInner
cannot access the inherited field super.x
, thus it accesses the field MyOuter.this.x
and sets its values to 100
. A consecutive call on the surrounding MyOuter
's getX()
will return 100
.
The call innerObj.getX()
(which is inherited from MyOuter
and can access super.x
) returns the value of the inherited field super.x
(still having its initial value of 3
).
If we remove the extends MyOuter
from and include the getX()
-method in MyInner
, the code behaves as expected.
The fact that MyInner
cannot access the inherited field private x
is confusing at first, but the behaviour is actually in line with the behaviour of the keyword protected
in the context of static mehthods in inheriting classes as discussed in this post by Hariharan
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论