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()` 方法。