JAVA内部类是否如何访问外部类的私有方法、私有成员变量

JAVA内部类是否如何访问外部类的私有方法、私有成员变量

talk is cheap,show me the code!

public class InnerClassMethodThis {

    private String deptName;

    public static void main(String[] args) {
        InnerClass innerClass = new InnerClassMethodThis().new InnerClass();
        innerClass.innerMethod();
    }

    private void method() {
        System.out.println(this);
    }

    class InnerClass {
        public void innerMethod() {
            method();
        }
    }

}

从代码已经看不出什么了。直接看汇编的字节码

内部类

D:\IdeaProjects\idea_mi_java\miJava\baseJava\target\classes>javap -v -p InnerClassMethodThis$InnerClass
Classfile /D:/IdeaProjects/idea_mi_java/miJava/baseJava/target/classes/InnerClassMethodThis$InnerClass.class
  Last modified 2024-5-11; size 607 bytes
  MD5 checksum f595837ecea2af97657b905ebb7f81af
  Compiled from "InnerClassMethodThis.java"
class InnerClassMethodThis$InnerClass
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Fieldref           #4.#22         // InnerClassMethodThis$InnerClass.this$0:LInnerClassMethodThis;
   #2 = Methodref          #5.#23         // java/lang/Object."<init>":()V
   #3 = Methodref          #24.#25        // InnerClassMethodThis.access$000:(LInnerClassMethodThis;)V
   #4 = Class              #26            // InnerClassMethodThis$InnerClass
   #5 = Class              #27            // java/lang/Object
   #6 = Utf8               this$0
   #7 = Utf8               LInnerClassMethodThis;
   #8 = Utf8               <init>
   #9 = Utf8               (LInnerClassMethodThis;)V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               LocalVariableTable
  #13 = Utf8               this
  #14 = Utf8               InnerClass
  #15 = Utf8               InnerClasses
  #16 = Utf8               LInnerClassMethodThis$InnerClass;
  #17 = Utf8               MethodParameters
  #18 = Utf8               innerMethod
  #19 = Utf8               ()V
  #20 = Utf8               SourceFile
  #21 = Utf8               InnerClassMethodThis.java
  #22 = NameAndType        #6:#7          // this$0:LInnerClassMethodThis;
  #23 = NameAndType        #8:#19         // "<init>":()V
  #24 = Class              #28            // InnerClassMethodThis
  #25 = NameAndType        #29:#9         // access$000:(LInnerClassMethodThis;)V
  #26 = Utf8               InnerClassMethodThis$InnerClass
  #27 = Utf8               java/lang/Object
  #28 = Utf8               InnerClassMethodThis
  #29 = Utf8               access$000
{
  final InnerClassMethodThis this$0;
    descriptor: LInnerClassMethodThis;
    flags: ACC_FINAL, ACC_SYNTHETIC

  InnerClassMethodThis$InnerClass(InnerClassMethodThis);
    descriptor: (LInnerClassMethodThis;)V
    flags:
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #1                  // Field this$0:LInnerClassMethodThis;
         5: aload_0
         6: invokespecial #2                  // Method java/lang/Object."<init>":()V
         9: return
      LineNumberTable:
        line 14: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   LInnerClassMethodThis$InnerClass;
            0      10     1 this$0   LInnerClassMethodThis;
    MethodParameters:
      Name                           Flags
      this$0                         final mandated

  public void innerMethod();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #1                  // Field this$0:LInnerClassMethodThis;
         4: invokestatic  #3                  // Method InnerClassMethodThis.access$000:(LInnerClassMethodThis;)V
         7: return
      LineNumberTable:
        line 16: 0
        line 17: 7
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       8     0  this   LInnerClassMethodThis$InnerClass;
}
SourceFile: "InnerClassMethodThis.java"
InnerClasses:
     #14= #4 of #24; //InnerClass=class InnerClassMethodThis$InnerClass of class InnerClassMethodThis

外部类

D:\IdeaProjects\idea_mi_java\miJava\baseJava\target\classes>javap -v -p InnerClassMethodThis
Classfile /D:/IdeaProjects/idea_mi_java/miJava/baseJava/target/classes/InnerClassMethodThis.class
  Last modified 2024-5-11; size 1052 bytes
  MD5 checksum 2adcbf1bf7a7b73bd77c50f00de68f9b
  Compiled from "InnerClassMethodThis.java"
public class InnerClassMethodThis
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#36         // InnerClassMethodThis.method:()V
   #2 = Methodref          #11.#37        // java/lang/Object."<init>":()V
   #3 = Class              #38            // InnerClassMethodThis$InnerClass
   #4 = Class              #39            // InnerClassMethodThis
   #5 = Methodref          #4.#37         // InnerClassMethodThis."<init>":()V
   #6 = Methodref          #11.#40        // java/lang/Object.getClass:()Ljava/lang/Class;
   #7 = Methodref          #3.#41         // InnerClassMethodThis$InnerClass."<init>":(LInnerClassMethodThis;)V
   #8 = Methodref          #3.#42         // InnerClassMethodThis$InnerClass.innerMethod:()V
   #9 = Fieldref           #43.#44        // java/lang/System.out:Ljava/io/PrintStream;
  #10 = Methodref          #45.#46        // java/io/PrintStream.println:(Ljava/lang/Object;)V
  #11 = Class              #47            // java/lang/Object
  #12 = Utf8               InnerClass
  #13 = Utf8               InnerClasses
  #14 = Utf8               deptName
  #15 = Utf8               Ljava/lang/String;
  #16 = Utf8               <init>
  #17 = Utf8               ()V
  #18 = Utf8               Code
  #19 = Utf8               LineNumberTable
  #20 = Utf8               LocalVariableTable
  #21 = Utf8               this
  #22 = Utf8               LInnerClassMethodThis;
  #23 = Utf8               main
  #24 = Utf8               ([Ljava/lang/String;)V
  #25 = Utf8               args
  #26 = Utf8               [Ljava/lang/String;
  #27 = Utf8               innerClass
  #28 = Utf8               LInnerClassMethodThis$InnerClass;
  #29 = Utf8               MethodParameters
  #30 = Utf8               method
  #31 = Utf8               access$000
  #32 = Utf8               (LInnerClassMethodThis;)V
  #33 = Utf8               x0
  #34 = Utf8               SourceFile
  #35 = Utf8               InnerClassMethodThis.java
  #36 = NameAndType        #30:#17        // method:()V
  #37 = NameAndType        #16:#17        // "<init>":()V
  #38 = Utf8               InnerClassMethodThis$InnerClass
  #39 = Utf8               InnerClassMethodThis
  #40 = NameAndType        #48:#49        // getClass:()Ljava/lang/Class;
  #41 = NameAndType        #16:#32        // "<init>":(LInnerClassMethodThis;)V
  #42 = NameAndType        #50:#17        // innerMethod:()V
  #43 = Class              #51            // java/lang/System
  #44 = NameAndType        #52:#53        // out:Ljava/io/PrintStream;
  #45 = Class              #54            // java/io/PrintStream
  #46 = NameAndType        #55:#56        // println:(Ljava/lang/Object;)V
  #47 = Utf8               java/lang/Object
  #48 = Utf8               getClass
  #49 = Utf8               ()Ljava/lang/Class;
  #50 = Utf8               innerMethod
  #51 = Utf8               java/lang/System
  #52 = Utf8               out
  #53 = Utf8               Ljava/io/PrintStream;
  #54 = Utf8               java/io/PrintStream
  #55 = Utf8               println
  #56 = Utf8               (Ljava/lang/Object;)V
{
  private java.lang.String deptName;
    descriptor: Ljava/lang/String;
    flags: ACC_PRIVATE

  public InnerClassMethodThis();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #2                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LInnerClassMethodThis;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=2, args_size=1
         0: new           #3                  // class InnerClassMethodThis$InnerClass
         3: dup
         4: new           #4                  // class InnerClassMethodThis
         7: dup
         8: invokespecial #5                  // Method "<init>":()V
        11: dup
        12: invokevirtual #6                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
        15: pop
        16: invokespecial #7                  // Method InnerClassMethodThis$InnerClass."<init>":(LInnerClassMethodThis;)V
        19: astore_1
        20: aload_1
        21: invokevirtual #8                  // Method InnerClassMethodThis$InnerClass.innerMethod:()V
        24: return
      LineNumberTable:
        line 6: 0
        line 7: 20
        line 8: 24
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  args   [Ljava/lang/String;
           20       5     1 innerClass   LInnerClassMethodThis$InnerClass;
    MethodParameters:
      Name                           Flags
      args

  private void method();
    descriptor: ()V
    flags: ACC_PRIVATE
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: aload_0
         4: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
         7: return
      LineNumberTable:
        line 11: 0
        line 12: 7
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       8     0  this   LInnerClassMethodThis;

  static void access$000(InnerClassMethodThis);
    descriptor: (LInnerClassMethodThis;)V
    flags: ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method method:()V
         4: return
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0    x0   LInnerClassMethodThis;
}
SourceFile: "InnerClassMethodThis.java"
InnerClasses:
     #12= #3 of #4; //InnerClass=class InnerClassMethodThis$InnerClass of class InnerClassMethodThis

##

从字节码层面可以看出编译器在外部类帮我们生成了一个静态方法static void access$000(InnerClassMethodThis)

在内部类构造器上面传入InnerClassMethodThis参数和内部类增加一个内部类成员变量InnerClassMethodThis

内部类成员变量

final InnerClassMethodThis this$0;
    descriptor: LInnerClassMethodThis;

内部类构造器

InnerClassMethodThis$InnerClass(InnerClassMethodThis);
    descriptor: (LInnerClassMethodThis;)V

内部调用外部类私有方法public void innerMethod()  实际上调用的是编译器生成的access$000方法

 4: invokestatic  #3                  // Method InnerClassMethodThis.access$000:(LInnerClassMethodThis;)V

结论:

内部类访问外部类私有方法或者私有成员方法,编译器是帮我们生成了一个静态方法给内部类调用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值