Java内部类是如何获取外部类的private属性

关于内部类是如何获取外部类的private属性

上一段代码:

public class OuterClass {
  private static String language = "en";
  private String region = "US";
  private String li;

  private void kk() {
    System.out.println("kk");
}

  public class InnerClass {
      public void printOuterClassPrivateFields() {
          String fields = "language=" + language +region;
          System.out.println(fields);
          kk();
      }
  }

  public static void main(String[] args) {
      OuterClass outer = new OuterClass();
      OuterClass.InnerClass inner = outer.new InnerClass();
      inner.printOuterClassPrivateFields();
  }
}

jdk1.8.0编译
反编译OuterClass:

public class OuterClass
{
  private static String language = "en";
  private String region = "US";
  private String li;

  private void kk()
  {
    System.out.println("kk");
  }

  public class InnerClass
  {
    public InnerClass() {}

    public void printOuterClassPrivateFields()
    {
      String fields = "language=" + OuterClass.language + OuterClass.this.region;
      System.out.println(fields);
      OuterClass.this.kk();
    }
  }

  public static void main(String[] args)
  {
    OuterClass outer = new OuterClass(); 
    OuterClass tmp13_12 = outer;
    tmp13_12.getClass();
    InnerClass inner = new InnerClass(tmp13_12);
    inner.printOuterClassPrivateFields();
  }
}

这是OuterClass$InnerClass的反编译:

public class OuterClass$InnerClass
{
  public OuterClass$InnerClass(OuterClass paramOuterClass) {}

  public void printOuterClassPrivateFields()
  {
    String fields = "language=" + OuterClass.access$0() + OuterClass.access$1(**this.this$0**);
    System.out.println(fields);
    OuterClass.access$2(this.this$0);
  }
}

我们可以看到OuterClass里面多了几个形如access$X()的静态方法
于是使用”javap -c “更深一步的反编译:

Compiled from "OuterClass.java"
public class a.OuterClass {
  static {};
    Code:
       0: ldc           #12                 // String en
       2: putstatic     #14                 // Field language:Ljava/lang/String;
       5: return        

  public a.OuterClass();
    Code:
       0: aload_0       
       1: invokespecial #19                 // Method java/lang/Object."<init>":()V
       4: aload_0       
       5: ldc           #21                 // String US
       7: putfield      #23                 // Field region:Ljava/lang/String;
      10: return        

  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class a/OuterClass
       3: dup           
       4: invokespecial #43                 // Method "<init>":()V
       7: astore_1      
       8: new           #44                 // class a/OuterClass$InnerClass
      11: dup           
      12: aload_1       
      13: dup           
      14: invokevirtual #46                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
      17: pop           
      18: invokespecial #50                 // Method a/OuterClass$InnerClass."<init>":(La/OuterClass;)V
      21: astore_2      
      22: aload_2       
      23: invokevirtual #53                 // Method a/OuterClass$InnerClass.printOuterClassPrivateFields:()V
      26: return        

  static java.lang.String access$0();
    Code:
       0: getstatic     #14                 // **Field language:Ljava/lang/String;**
       3: areturn       

  static java.lang.String access$1(a.OuterClass);
    Code:
       0: aload_0       
       1: getfield      #23                 // **Field region:Ljava/lang/String;**
       4: areturn       

  static void access$2(a.OuterClass);
    Code:
       0: aload_0       
       1: invokespecial #66                 // **Method kk:()V**
       4: return        
}

这些代码都不好看,直接看注释好了。
我们可以看到,编译器帮我们生成了三个方法:access 0(),access 1(),access 2()languageregionkk()access X的名字)

总结:
1、当内部类调用外部类的私有属性(包括变量和方法)时,其真正的执行是调用了编译器生成的属性的静态方法(即acess 0,access 1等)来获取这些属性值或调用方法。
(附:外部类访问内部类的private属性也是一样的)
(再附:其中java官方文档 有这样一句话

if the member or constructor is declared private, then access is
permitted if and only if it occurs within the body of the top level
class (§7.6) that encloses the declaration of the member or
constructor.
意思是 如果(内部类的)成员和构造方法设定成了私有修饰符,当且仅当其外部类访问时是允许的。)

2、编译器编译的时候,在内部类中,会生成一个this$0的变量,这个变量应该就是外部类的实例 (附:为什么非静态内部类有可能造成内存泄漏:因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有。)

本文参考:http://droidyue.com/blog/2014/10/02/the-private-modifier-in-java/

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值