添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
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 调用类的私有方法,构造函数

Java中内部类是如何调用外部类的成员变量和方法的?我们下看看下面的例子package com.iworktool.libjava;public class Outer{ private String privateValue = "privateValue"; public String publicValue = "publicValue"; private class Inner{ public Inner() {} 2 class A{ 3 void fA(){ 4 System.out.println("we are students"); 5 ... class Outer{        // 定义外部类       private static String info = "hello world" ;    // 定义外部类的私有属性       static class In public void printInfo() { System.out.println("Number: " + number); System.out.println("Name: " + name); 在上面的示例中,`number` 和 `name` 是 `MyClass` 类的成员变量。构造函数 `MyClass(int number, String name)` 用于初始化这些成员变量。`printInfo()` 方法用于打印成员变量的值。 要创建 `MyClass` 类的对象,可以使用 `new` 关键字和构造函数,如下所示: MyClass obj = new MyClass(1, "John"); 在上面的示例中,`obj` 是 `MyClass` 类的对象,并传递了参数 `1` 和 `"John"` 给构造函数。 要调用 `MyClass` 类的方法,可以使用对象名和点号运算符,如下所示: obj.printInfo(); 在上面的示例中,我们使用 `obj` 对象调用了 `printInfo()` 方法