内部类对象

huangapple go评论89阅读模式
英文:

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&#39;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&#39;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(&quot;x: &quot; + innerObj.getX()); //x: 3
    System.out.println(&quot;x: &quot; + 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 from MyOuter, but inaccessible because it is declared as private, and MyInner as an inheriting object cannot access this field.
  • One field MyOuter.this.x from the sorrounding MyOuter-instance (since MyInner is a (non-static) inner class, it is always bound to an instance of the surrounding MyOuter), 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

huangapple
  • 本文由 发表于 2020年9月19日 06:16:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/63963463.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定