为什么内部类的private变量可被外部类直接访问?

https://www.zhihu.com/question/54730071

问题:

我的意思是外部类通过内部类对象访问内部类私有变量,是怎么做到的?

回答:

题主以后请直接把例子的代码以文本形式放到问题描述中。截图的话等于迫使别人再打一次字…虽然截图已经比手机拍照要好了orz

题主问的代码是像这样的:

public class Outer {
  private int outProp = 8;
  class Inner {
    private int inProp = 5;
  }

  public void accessInnerProp() {
    System.out.println(new Inner().inProp);
  }

  public static void main(String[] args) {
    Outer p = new Outer();
    p.accessInnerProp();
  }
}

Java语言规范里只说了enclosing class可以访问inner class的private/protected成员,inner class也可以访问enclosing class的private/protected成员,但是没有规定死要如何实现这种访问。

JVM规范则在大多数时候都把每个Class都看作等价于top-level的,也就是说不关心enclosing / inner class之间的嵌套关系。对JVM来说,enclosing class和inner class在大部分情况下都是“不相关的两个类”,所以它们之间相互是不能访问对方的private/protected成员的。

在实现中,衔接Java语言规范与JVM规范的就是Java源码级编译器(例如javac、ECJ等)。既然规范没规定死要如何实现,各个编译器都可以自己发明自己的办法。下面就说说javac的做法。

javac会把上面的代码解糖为类似下面的形式:

public class Outer {
  private int outProp;

  public Outer() {
    super();
    this.outProp = 8;
  }

  public void accessInnerProp() {
    System.out.println(Outer$Inner.access$000(new Outer$Inner(this)));
  }

  public static void main(String[] args) {
    Outer p = new Outer();
    p.accessInnerProp();
  }
}

class Outer$Inner {
  private int inProp;
  final /* synthetic */ Outer this$0;

  Outer$Inner(Outer outer) {
    this.this$0 = outer;
    super();
    this.inProp = 5;
  }

  static /* synthetic */ int access$000(Outer$Inner self) {
    return self.inProp;
  }
}

所以,简单来说就是在enclosing / inner class之间要访问对方的private/protected成员时,javac会生成合适的“access method”(上面的access$xxx形式的方法)来提供合适的可访问性,这样就绕开了原本的成员的可访问性不足的问题。

但这种Java语言与JVM之间的不匹配有时候会让一些程序要用非常蛋疼的代码来实现,特别是需要做动态字节码生成的时候。

所以Java核心开发组也有在考虑在未来的Java版本中让JVM能更主动的识别类之间的嵌套关系,并直接在JVM层面上让enclosing / inner class之间有合适的可访问性,这样就不用再依赖Java源码级编译器的magic了。

放个传送门:

java的类似access$这样开头的方法的命名规则是什么? - RednaxelaFX 的回答 - 知乎

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值