Java内部类调用外部类对象的方法和成员函数过程

本文详细分析了Java内部类如何调用外部类的成员变量和方法,通过反编译class文件展示了系统如何通过代理方式实现这一访问。内部类在编译后会增加对外部类的引用,并使用静态方法访问私有成员,确保内部类可以正常操作外部类的私有属性和方法。
摘要由CSDN通过智能技术生成

Java中内部类是如何调用外部类的成员变量和方法的?我们下看看下面的例子

package com.iworktool.libjava;

public class Outer{
    private String privateValue = "privateValue";
    public String publicValue = "publicValue";

    private class Inner{
        public Inner()
        {}
        public void innerPrint()
        {
            privatePrint();
            System.out.println(privateValue);
            publicPrint();
        }
    }
    public Outer()
    {
        Inner inner = new Inner();
        inner.innerPrint();
    }

    private void privatePrint()
    {
        System.out.println(privateValue);
    }

    public void publicPrint()
    {
        System.out.println(publicValue);
    }
}

用javap反编译Outer类生成的class文件

public class com.iworktool.libjava.Outer {
  private java.lang.String privateValue;

  public java.lang.String publicValue;

  public com.iworktool.libjava.Outer();
    Code:
       0: aload_0
       1: invokespecial #3                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: ldc           #4                  // String privateValue
       7: putfield      #1                  // Field privateValue:Ljava/lang/String;
      10: aload_0
      11: ldc           #5                  // String publicValue
      13: putfield      #6                  // Field publicValue:Ljava/lang/String;
      16: new           #7                  // class com/iworktool/libjava/Outer$Inner
      19: dup
      20: aload_0
      21: aconst_null
      22: invokespecial #8                  // Method com/iworktool/libjava/Outer$Inner."<init>":(Lcom/iworktool/libjava/Outer;Lcom/iworktool/libjava/Outer$1;)V
      25: astore_1
      26: aload_1
      27: invokevirtual #9                  // Method com/iworktool/libjava/Outer$Inner.innerPrint:()V
      30: return

  private void print();
    Code:
       0: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: aload_0
       4: getfield      #1                  // Field privateValue:Ljava/lang/String;
       7: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      10: return

  public void publicPrint();
    Code:
       0: return

  static void access$000(com.iworktool.libjava.Outer);
    Code:
       0: aload_0
       1: invokespecial #2                  // Method print:()V
       4: return

  static java.lang.String access$100(com.iworktool.libjava.Outer);
    Code:
       0: aload_0
       1: getfield      #1                  // Field privateValue:Ljava/lang/String;
       4: areturn
}

可以看出系统为我们新增加了Default静态方法static void access$000和Default静态成员变量java.lang.String access$100

这两个分别对应了Outer类的私有方法privatePrint和私有成员变量privateValue,通过这种代理的方式就可以让内部类对象能访问到外部类的私有成员和方法

在看看Inner类反编译后的情况

class com.iworktool.libjava.Outer$Inner {
  final com.iworktool.libjava.Outer this$0;

  public com.iworktool.libjava.Outer$Inner(com.iworktool.libjava.Outer);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #1                  // Field this$0:Lcom/iworktool/libjava/Outer;
       5: aload_0
       6: invokespecial #2                  // Method java/lang/Object."<init>":()V
       9: return

  public void innerPrint();
    Code:
       0: aload_0
       1: getfield      #1                  // Field this$0:Lcom/iworktool/libjava/Outer;
       4: invokestatic  #3                  // Method com/iworktool/libjava/Outer.access$000:(Lcom/iworktool/libjava/Outer;)V
       7: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: aload_0
      11: getfield      #1                  // Field this$0:Lcom/iworktool/libjava/Outer;
      14: invokestatic  #5                  // Method com/iworktool/libjava/Outer.access$100:(Lcom/iworktool/libjava/Outer;)Ljava/lang/String;
      17: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      20: aload_0
      21: getfield      #1                  // Field this$0:Lcom/iworktool/libjava/Outer;
      24: invokevirtual #7                  // Method com/iworktool/libjava/Outer.publicPrint:()V
      27: return
}

可以看出,系统主动给我们的内部类增加了一个类型为外部类的成员变量 final com.iworktool.libjava.Outer this$0; 并且新增了一个带参构造函数public com.iworktool.libjava.Outer$Inner(com.iworktool.libjava.Outer);在外部类创建内部类对象的时候,会默认把外部类对象传入,这样就可以在内部类中访问外部类对象的成员变量和方法。

在反编译后的代码中有下面几个字节码

invokeinterface  调用接口方法

invokevirtual   调用类的public方法

invokestatic 调用类的静态方法

invokespecial 调用类的私有方法,构造函数

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值