内部类与外部类的私有字段和私有方法的相互访问

  最近学了下aop,并利用asm进行了实践,开发了一个Android的插件(https://github.com/zhoujucheng/bladeaop),使用这个插件的时候发现了一些我不认识的方法,研究了下发现是编译器生成的方法,目的是是解决内部类与外部类的私有字段和私有方法的相互访问的问题。
  首先需要知道是内部类是会被编译成一个单独的class文件,从这个角度看的话内部类和普通的类是区别并不大,然而这样的话,外部类是如何能访问到内部类的私有字段和私有方法呢?或者反过来说内部类是如何能访问到外部类的私有字段和私有方法呢?

public class OuterClass {

    private InnerClass innerClass = new InnerClass();
    
    public void test(){
        System.out.println(innerClass.innerString);
    }

    private class InnerClass{
        private String innerString = "Hello world!";
    }
}


可以看到,InnerClass被编译成了OuterClass$InnerClass.class。通过javap -c OuterClass$InnerClass.class得到:

class OuterClass$InnerClass {
  final OuterClass this$0;

  OuterClass$InnerClass(OuterClass);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #2                  // Field this$0:LOuterClass;
       5: aload_0
       6: invokespecial #3                  // Method java/lang/Object."<init>":()V
       9: aload_0
      10: ldc           #4                  // String Hello world!
      12: putfield      #1                  // Field innerString:Ljava/lang/String;
      15: return

  static java.lang.String access$000(OuterClass$InnerClass);
    Code:
       0: aload_0
       1: getfield      #1                  // Field innerString:Ljava/lang/String;
       4: areturn
}

  从反编译得到的字节码可以看出,多了一个access$000方法,而且是一个static,参数为OuterClass$InnerClass对象,看到这样总算明白了,编译器为我们生成了static方法,然后通过传入内部类的对象访问私有字段和方法。这个内部类像下面这样:

class OuterClass$InnerClass {
    private String innerString = "Hello world!";
    static String access$000(OuterClass$InnerClass innerClass){
        return innerClass.innerString;
    }
}

  其实内部类访问外部类的私有字段和方法用的也是同一个套路,首先编译器会为内部类生成一个带有外部类参数的构造器,上面的字节码也已经体现出来了,从上面的字节码可以看出,外部类的对象引用会被保存到了内部类的this$0里,当内部类访问外部类的私有字段或方法时,实际上会调用外部类的由编译器生成的static方法,并将内部类的this$0传过去,然后外部类的static方法利用这个参数达到访问私有字段和方法的目的。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Java中,内部类可以直接访问外部类的成员(包括方法字段),即使它们是私有的。你可以通过以下几种方式在内部类中调用外部类的方法: 1. 在内部类的方法中使用外部类的实例:如果内部类是非静态的,你可以通过创建外部类的实例来调用外部类的方法。例如: ```java public class OuterClass { private void outerMethod() { System.out.println("Outer method"); } public class InnerClass { public void innerMethod() { outerMethod(); // 调用外部类的方法 } } } ``` 在上面的例子中,内部类InnerClass可以直接调用外部类OuterClass的方法outerMethod()。 2. 在静态内部类中使用外部类的方法:如果内部类是静态的,它不能直接访问外部类的实例方法,但可以通过创建外部类的实例或使用外部类的类名来调用外部类的静态方法。例如: ```java public class OuterClass { private static void outerStaticMethod() { System.out.println("Outer static method"); } public static class InnerClass { public void innerMethod() { OuterClass.outerStaticMethod(); // 通过外部类的类名调用外部类的静态方法 } } } ``` 在上面的例子中,内部类InnerClass可以通过OuterClass.outerStaticMethod()来调用外部类OuterClass的静态方法。 请注意,如果内部类是私有的,它只能在外部类的内部访问。如果你需要在外部外部访问内部类的方法,你可以提供一个公共的方法外部类中调用内部类的方法。 希望这个回答能够解决你的问题。如果还有其他疑问,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值