类名称$内部类.class 三、内部类分类分类 ...

java:内部类分类及访问方法详解

一、定义:
在一个类中定义另外一个类
二、内部类特点:
1、内部类成员可以访问外部类属性,包括私有属性
2、源类文件命名: 外部类名称$内部类.class
三、内部类分类

分类解释
成员内部类在外部类成员位置定义了一个类,默认非静态
局部内部类在外部类方法中定义类
匿名内部类(重点)内部类简化方式

四、访问方式

访问类型访问方法
外部类访问内部类外部类名.内部类名 对象名=new 外部名().new 内部类名();
private修饰的内部类方法访问new 外部类.内部类方法();
static修饰的内部类访问外部类名.内部类名 对象名=new 外部类对象().内部类对象();
内部类static成员访问方法外部类名.内部类名.方法名();
局部内部类访问new 外部类名.局部方法(); (局部方法中的局部内部类做实例化)
内部类访问外部类属性外部类名.this.属性名;

五、注意事项
1、局部内部类 访问 局部变量,局部变量需加入final关键字修饰,否则报错;
JDK8之后版本自动加入final;
2、静态内部类成员方法 只可以访问 外部类静态成员。
六、匿名内部类
//匿名内部类格式 new 类名/接口名(){	方法/重写方法 }; //注意:匿名内部类只可在局部使用!
文章目录1内部类的基本概念1.1内部类的定义1.2内部类的优缺点2 创建内部类2.1 在外部类外部创建非静态内部类2.2 在外部类外部创建静态内部类2.3 在外部类内部创建内部类语法3内部类的分类3.1 成员内部类3.2 静态...

文章目录

1. 内部类的基本概念

1.1 内部类的定义

内部类:所谓内部类就是在一个类内部进行其他类结构的嵌套操作。
classOuter{private String str="外部类中的字符串";//**************************//定义一个内部类classInner{private String inStr="内部类中的字符串";//定义一个普通方法publicvoidprint(){//调用外部类的str属性 System.out.println(str);}}//**************************//在外部类中定义一个方法,该方法负责产生内部类对象并调用print()方法publicvoidfun(){//内部类对象 Inner in=newInner();//内部类对象提供的print in.print();}}publicclassTest{publicstaticvoidmain(String[] args){//创建外部类对象 Outer out=newOuter();//外部类方法 out.fun();}}
运行结果:外部类中的字符串
但是如果去掉内部类:
classOuter{private String outStr="Outer中的字符串";public StringgetOutStr(){return outStr;}publicvoidfun(){//2//this表示当前对象 Inner in=newInner(this);//3 in.print();//5}}classInner{private String inStr="Inner中的字符串";private Outer out;//构造注入publicInner(Outer out)//3{this.out=out;//4.为Inner中的out变量初始化}publicvoidprint(){//6 System.out.println(out.getOutStr());//7}}publicclassTest{publicstaticvoidmain(String[] args){ Outer out=newOuter();//1. out.fun();//2.}}
执行结果:Outer中的字符串
但是去掉内部类之后发现程序更加难以理解。

1.2 内部类的优缺点

内部类的优点:
内部类与外部类可以方便的访问彼此的私有域(包括私有方法、私有属性)。内部类是另外一种封装,对外部的其他类隐藏。内部类可以实现java的单继承局限。
内部类的缺点:
结构复杂。
记录:使用内部类实现多继承:
classA{private String name="A类的私有域";public StringgetName(){return name;}}classB{privateint age=20;publicintgetAge(){return age;}}classOutter{privateclassInnerClassAextendsA{public Stringname(){returnsuper.getName();}}privateclassInnerClassBextendsB{publicintage(){returnsuper.getAge();}}public Stringname(){returnnewInnerClassA().name();}publicintage(){returnnewInnerClassB().age();}}publicclassTest2{publicstaticvoidmain(String[] args){ Outter outter=newOutter(); System.out.println(outter.name()); System.out.println(outter.age());}}
2. 创建内部类

2.1 在外部类外部 创建非静态内部类

语法:外部类.内部类 内部类对象 = new 外部类().new 内部类();
举例:Outer.Inner in = new Outer().new Inner();

2.2 在外部类外部 创建静态内部类

语法:外部类.内部类 内部类对象 = new 外部类.内部类();
举例:Outer.Inner in = new Outer.Inner();

2.3 在外部类内部创建内部类语法

在外部类内部创建内部类,就像普通对象一样直接创建:Inner in = new Inner();
3. 内部类的分类
在Java中内部类主要分为成员内部类、静态内部类、方法内部类、匿名内部类

3.1 成员内部类

类比成员方法
成员内部类内部不允许存在任何static变量或方法 正如成员方法中不能有任何静态属性 (成员方法与对象相关、静态属性与类有关)classOuter{private String name="test";publicstaticint age=20;classInner{publicstaticint num=10;publicvoidfun(){ System.out.println(name); System.out.println(age);}}}publicclassTest{publicstaticvoidmain(String[] args){}}
2. 成员内部类是依附外部类的,只有创建了外部类才能创建内部类。

3.2 静态内部类

关键字static可以修饰成员变量、方法、代码块、其实还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,静态内部类和非静态内部类之间存在一个最大的区别,非静态内部类在编译完成之后会隐含的保存着一个引用,该引用是指向创建它的外围类,但是静态类没有。没有这个引用就意味着:
1.静态内部类的创建不需要依赖外部类可以直接创建。
2.静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。
classOuter{public String name="test";privatestaticint age=20;staticclassInner{private String name;publicvoidfun(){ System.out.println(name); System.out.println(age);}}}publicclassTest{publicstaticvoidmain(String[] args){ Outer.Inner in=newOuter.Inner();}}

3.3 方法内部类

方法内部类顾名思义就是定义在方法里的类
1.方法内部类不允许使用访问权限修饰符(public、private、protected)均不允许。
classOuter{privateint num=5;publicvoiddispaly(finalint temp){//方法内部类即嵌套在方法里面publicclassInner{}}}publicclassTest{publicstaticvoidmain(String[] args){}}
2. 方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问 (换句话说其他方法或者类都不知道有这个类的存在)方法内部类对外部完全隐藏,出了创建这个类的方法可以访问它,其他地方均不能访问。
3. 方法内部类如果想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)
classOuter{privateint num=5;//普通方法publicvoiddispaly(int temp){//方法内部类即嵌套在方法里面classInner{publicvoidfun(){ System.out.println(num); temp++; System.out.println(temp);}}//方法内部类在方法里面创建newInner().fun();}}publicclassTest{publicstaticvoidmain(String[] args){ Outer out=newOuter(); out.dispaly(2);}}

3.4 匿名内部类

匿名内部类就是一个没有名字的方法内部类,因此特点和方法与方法内部类完全一致,除此之外,还有自己的特点:
1.匿名内部类必须继承一个抽象类或者实现一个接口。
2.匿名内部类没有类名,因此没有构造方法。
//匿名内部类//声明一个接口interfaceMyInterface{//接口中方法没有方法体voidtest();}classOuter{privateint num=5;publicvoiddispaly(int temp){//匿名内部类,匿名的实现了MyInterface接口//隐藏的class声明newMyInterface(){publicvoidtest(){ System.out.println("匿名实现MyInterface接口"); System.out.println(temp);}}.test();}}publicclassTest{publicstaticvoidmain(String[] args){ Outer out=newOuter(); out.dispaly(3);}}
4. 内部类与外部类的关系
对于非静态的内部类,内部类的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的。内部类可以直接访问外部类的元素(包括私有域)—外部类在内部类之前创建,创建内部类时会将外部类的对象传入classOuter{//成员变量 与对象有关private String msg;privateint age;//--------------------------classInner{publicvoiddispaly(){//此处有一个隐藏的Outer.this msg="test"; age=20; System.out.println(msg); System.out.println(age);}}//--------------------------publicvoidtest(){ Inner in=newInner(); in.dispaly();}}publicclassTest{publicstaticvoidmain(String[] args){ Outer out=newOuter(); out.test();}}外部类可以通过内部类的引用间接访问内部类元素– -要想访问内部类属性,必须先创建内部类对象classOuter{publicvoiddispaly(){//外部类通过创建内部类的对象间接访问内部类元素 Inner in=newInner(); in.dispaly();}classInner{publicvoiddispaly(){ System.out.println("内部类");}}}publicclassTest1{publicstaticvoidmain(String[] args){ Outer out=newOuter(); out.dispaly();}}内部类是一个相对独立的个体,与外部类没有关系。
二、内部类的分类 1、成员内部类 2、局部内部类 三、匿名内部类 1、匿名内部类含义 2、匿名内部类的作用与格式 一、概述 将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类...
目录
一、概述
将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称之为内部类,其他类称之为外部类。在描述事物的时候,若一个事物内部还包含其他可能包含的事物,这时,就可以使用内部类来进行描述。
eg:
class 汽车{ // 外部类 class 发动机{ //内部类 } }
二、内部类的分类
成员内部类局部内部类
我们在定义内部类的时候,就是一个正常定义类的过程,同样包含各种修饰符、继承与实现关系等,在内部类中可以直接访问外部类的所有成员

1、成员内部类

成员内部类,定义在外部类中的成员位置,与类中的成员变量相似,可以通过外部类对象进行访问
定义格式:
class 外部类{
修饰符 class 内部类{
//XXX
}
}访问方式:
外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
代码实例:
//定义类 class Body { //外部类,身体 private boolean life= true; //生命状态 public class Heart { //内部类,心脏 public void jump() { System.out.println("心脏噗通噗通的跳") System.out.println("生命状态" + life); //访问外部类成员变量 } } }//访问内部类 public static void main(String[] args) { //创建内部类对象 Body.Heart bh = new Body().new Heart(); //调用内部类中的方法 bh.jump(); }

2、局部内部类

局部内部类,定义在外部类方法中的局部位置,与访问方法中的局部变量相似,可以通过调用方法进行访问
定义格式:
class 外部类 {
修饰符 返回值类型 方法名(参数){
class 内部类 {
//XXX
}
}
}访问方法
在外部类方法中,创建内部类对象进行访问
代码实例:
//定义类 class Party { //外部类,聚会 public void puffBall(){ // 吹气球方法 class Ball { // 内部类,气球 public void puff(){ System.out.println("气球膨胀了"); } } //创建内部类对象,调用puff方法 new Ball().puff(); } }//访问内部类 public static void main(String[] args) { //创建外部类对象 Party p = new Party(); //调用外部类中的puffBall方法 p.puffBall(); }
三、匿名内部类
内部类是为了应对更为复杂的类之间的关系,在查看源码时会涉及到,而在开发过程中很少遇到,比较常用的内部类就是匿名内部类了,它是局部内部类的一种

1、匿名内部类含义

临时定义某一指定类型的子类定义后即可创建刚刚定义的这个子类的对象

2、匿名内部类的作用与格式

作用:匿名内部类是创建某个类型子类对象的快捷方式格式:
new 父类或接口() {
//方法重写
};//已经存在的父类: public abstract class Person{ public abstract void eat(); } //定义并创建该父类的子类对象,并用多态的方式赋值给父类引用变量 Person p = new Person(){ public void eat() { System.out.println(“我吃了”); } }; //调用eat方法 p.eat();使用匿名对象的方式,将定义子类与创建子类对象两个步骤由一个格式一次完成匿名内部如果不定义变量引用,则也是匿名对象:new Person(){ public void eat() { System.out.println(“我吃了”); } }.eat();
内部类在Java 里面算是非常常见的一个功能了,在日常开发中我们肯定多多少少都用过,这里总结一下关于Java中内部类的相关知识点和一些使用内部类时需要注意的点。 从种类上说,内部类可以分为四类:普通内部类...
*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

文章目录

前言

内部类在 Java 里面算是非常常见的一个功能了,在日常开发中我们肯定多多少少都用过,这里总结一下关于 Java 中内部类的相关知识点和一些使用内部类时需要注意的点。
从种类上说,内部类可以分为四类:普通内部类、静态内部类、匿名内部类、局部内部类。我们来一个个看:

注

本文所有实践代码在 JDK1.8 版本进行验证。
普通内部类
这个是最常见的内部类之一了,其定义也很简单,在一个类里面作为类的一个字段直接定义就可以了,例:
publicclassInnerClassTest{publicclassInnerClassA{}}
在这里InnerClassA类为InnerClassTest类的普通内部类,在这种定义方式下,普通内部类对象依赖外部类对象而存在,即在创建一个普通内部类对象时首先需要创建其外部类对象,我们在创建上面代码中的InnerClassA对象时先要创建InnerClassTest对象,例:
publicclassInnerClassTest{publicint outField1=1;protectedint outField2=2;int outField3=3;privateint outField4=4;publicInnerClassTest(){// 在外部类对象内部,直接通过 new InnerClass(); 创建内部类对象 InnerClassA innerObj=newInnerClassA(); System.out.println("创建 "+this.getClass().getSimpleName()+" 对象"); System.out.println("其内部类的 field1 字段的值为: "+ innerObj.field1); System.out.println("其内部类的 field2 字段的值为: "+ innerObj.field2); System.out.println("其内部类的 field3 字段的值为: "+ innerObj.field3); System.out.println("其内部类的 field4 字段的值为: "+ innerObj.field4);}publicclassInnerClassA{publicint field1=5;protectedint field2=6;int field3=7;privateint field4=8;// static int field5 = 5; // 编译错误!普通内部类中不能定义 static 属性publicInnerClassA(){ System.out.println("创建 "+this.getClass().getSimpleName()+" 对象"); System.out.println("其外部类的 outField1 字段的值为: "+ outField1); System.out.println("其外部类的 outField2 字段的值为: "+ outField2); System.out.println("其外部类的 outField3 字段的值为: "+ outField3); System.out.println("其外部类的 outField4 字段的值为: "+ outField4);}}publicstaticvoidmain(String[] args){ InnerClassTest outerObj=newInnerClassTest();// 不在外部类内部,使用:外部类对象. new 内部类构造器(); 的方式创建内部类对象// InnerClassA innerObj = outerObj.new InnerClassA();}}
这里的内部类就像外部类声明的一个属性字段一样,因此其的对象时依附于外部类对象而存在的,我们来看一下结果:
我们注意到,内部类对象可以访问外部类对象中所有访问权限的字段,同时,外部类对象也可以通过内部类的对象引用来访问内部类中定义的所有访问权限的字段,后面我们将从源码里面分析具体的原因。
我们下面来看一下静态内部类:
静态内部类
我们知道,一个类的静态成员独立于这个类的任何一个对象存在,只要在具有访问权限的地方,我们就可以通过类名.静态成员名的形式来访问这个静态成员,同样的,静态内部类也是作为一个外部类的静态成员而存在,创建一个类的静态内部类对象不需要依赖其外部类对象。例:
publicclassInnerClassTest{publicint field1=1;publicInnerClassTest(){ System.out.println("创建 "+this.getClass().getSimpleName()+" 对象");// 创建静态内部类对象 StaticClass innerObj=newStaticClass(); System.out.println("其内部类的 field1 字段的值为: "+ innerObj.field1); System.out.println("其内部类的 field2 字段的值为: "+ innerObj.field2); System.out.println("其内部类的 field3 字段的值为: "+ innerObj.field3); System.out.println("其内部类的 field4 字段的值为: "+ innerObj.field4);}staticclassStaticClass{publicint field1=1;protectedint field2=2;int field3=3;privateint field4=4;// 静态内部类中可以定义 static 属性staticint field5=5;publicStaticClass(){ System.out.println("创建 "+ StaticClass.class.getSimpleName()+" 对象");// System.out.println("其外部类的 field1 字段的值为: " + field1); // 编译错误!!}}publicstaticvoidmain(String[] args){// 无需依赖外部类对象,直接创建内部类对象// InnerClassTest.StaticClass staticClassObj = new InnerClassTest.StaticClass(); InnerClassTest outerObj=newInnerClassTest();}}
结果:
可以看到,静态内部类就像外部类的一个静态成员一样,创建其对象无需依赖外部类对象(访问一个类的静态成员也无需依赖这个类的对象,因为它是独立于所有类的对象的)。但是于此同时,静态内部类中也无法访问外部类的非静态成员,因为外部类的非静态成员是属于每一个外部类对象的,而本身静态内部类就是独立外部类对象存在的,所以静态内部类不能访问外部类的非静态成员,而外部类依然可以访问静态内部类对象的所有访问权限的成员,这一点和普通内部类无异。
匿名内部类
匿名内部类有多种形式,其中最常见的一种形式莫过于在方法参数中新建一个接口对象 / 类对象,并且实现这个接口声明 / 类中原有的方法了:
publicclassInnerClassTest{publicint field1=1;protectedint field2=2;int field3=3;privateint field4=4;publicInnerClassTest(){ System.out.println("创建 "+this.getClass().getSimpleName()+" 对象");}// 自定义接口interfaceOnClickListener{voidonClick(Object obj);}privatevoidanonymousClassTest(){// 在这个过程中会新建一个匿名内部类对象,// 这个匿名内部类实现了 OnClickListener 接口并重写 onClick 方法 OnClickListener clickListener=newOnClickListener(){// 可以在内部类中定义属性,但是只能在当前内部类中使用,// 无法在外部类中使用,因为外部类无法获取当前匿名内部类的类名,// 也就无法创建匿名内部类的对象int field=1;@OverridepublicvoidonClick(Object obj){ System.out.println("对象 "+ obj+" 被点击"); System.out.println("其外部类的 field1 字段的值为: "+ field1); System.out.println("其外部类的 field2 字段的值为: "+ field2); System.out.println("其外部类的 field3 字段的值为: "+ field3); System.out.println("其外部类的 field4 字段的值为: "+ field4);}};// new Object() 过程会新建一个匿名内部类,继承于 Object 类,// 并重写了 toString() 方法 clickListener.onClick(newObject(){@Overridepublic StringtoString(){return"obj1";}});}publicstaticvoidmain(String[] args){ InnerClassTest outObj=newInnerClassTest(); outObj.anonymousClassTest();}}
来看看结果:
上面的代码中展示了常见的两种使用匿名内部类的情况:
1、直接 new 一个接口,并实现这个接口声明的方法,在这个过程其实会创建一个匿名内部类实现这个接口,并重写接口声明的方法,然后再创建一个这个匿名内部类的对象并赋值给前面的OnClickListener类型的引用;
2、new 一个已经存在的类 / 抽象类,并且选择性的实现这个类中的一个或者多个非final的方法,这个过程会创建一个匿名内部类对象继承对应的类 / 抽象类,并且重写对应的方法。
同样的,在匿名内部类中可以使用外部类的属性,但是外部类却不能使用匿名内部类中定义的属性,因为是匿名内部类,因此在外部类中无法获取这个类的类名,也就无法得到属性信息。
局部内部类
局部内部类使用的比较少,其声明在一个方法体 / 一段代码块的内部,而且不在定义类的定义域之内便无法使用,其提供的功能使用匿名内部类都可以实现,而本身匿名内部类可以写得比它更简洁,因此局部内部类用的比较少。来看一个局部内部类的小例子:
publicclassInnerClassTest{publicint field1=1;protectedint field2=2;int field3=3;privateint field4=4;publicInnerClassTest(){ System.out.println("创建 "+this.getClass().getSimpleName()+" 对象");}privatevoidlocalInnerClassTest(){// 局部内部类 A,只能在当前方法中使用classA{// static int field = 1; // 编译错误!局部内部类中不能定义 static 字段publicA(){ System.out.println("创建 "+ A.class.getSimpleName()+" 对象"); System.out.println("其外部类的 field1 字段的值为: "+ field1); System.out.println("其外部类的 field2 字段的值为: "+ field2); System.out.println("其外部类的 field3 字段的值为: "+ field3); System.out.println("其外部类的 field4 字段的值为: "+ field4);}} A a=newA();if(true){// 局部内部类 B,只能在当前代码块中使用classB{publicB(){ System.out.println("创建 "+ B.class.getSimpleName()+" 对象"); System.out.println("其外部类的 field1 字段的值为: "+ field1); System.out.println("其外部类的 field2 字段的值为: "+ field2); System.out.println("其外部类的 field3 字段的值为: "+ field3); System.out.println("其外部类的 field4 字段的值为: "+ field4);}} B b=newB();}// B b1 = new B(); // 编译错误!不在类 B 的定义域内,找不到类 B,}publicstaticvoidmain(String[] args){ InnerClassTest outObj=newInnerClassTest(); outObj.localInnerClassTest();}}
同样的,在局部内部类里面可以访问外部类对象的所有访问权限的字段,而外部类却不能访问局部内部类中定义的字段,因为局部内部类的定义只在其特定的方法体 / 代码块中有效,一旦出了这个定义域,那么其定义就失效了,就像代码注释中描述的那样,即外部类不能获取局部内部类的对象,因而无法访问局部内部类的字段。最后看看运行结果:
内部类的嵌套
内部类的嵌套,即为内部类中再定义内部类,这个问题从内部类的分类角度去考虑比较合适:
普通内部类:在这里我们可以把它看成一个外部类的普通成员方法,在其内部可以定义普通内部类(嵌套的普通内部类),但是无法定义static修饰的内部类,就像你无法在成员方法中定义static类型的变量一样,当然也可以定义匿名内部类和局部内部类;
静态内部类:因为这个类独立于外部类对象而存在,我们完全可以将其拿出来,去掉修饰它的static关键字,他就是一个完整的类,因此在静态内部类内部可以定义普通内部类,也可以定义静态内部类,同时也可以定义static成员;
匿名内部类:和普通内部类一样,定义的普通内部类只能在这个匿名内部类中使用,定义的局部内部类只能在对应定义域内使用;
局部内部类:和匿名内部类一样,但是嵌套定义的内部类只能在对应定义域内使用。
深入理解内部类
不知道小伙伴们对上面的代码有没有产生疑惑:非静态内部类可以访问外部类所有访问权限修饰的字段(即包括了private权限的),同时,外部类也可以访问内部类的所有访问权限修饰的字段。而我们知道,private权限的字段只能被当前类本身访问。然而在上面我们确实在代码中直接访问了对应外部类 / 内部类的private权限的字段,要解除这个疑惑,只能从编译出来的类下手了,为了简便,这里采用下面的代码进行测试:
publicclassInnerClassTest{int field1=1;privateint field2=2;publicInnerClassTest(){ InnerClassA inner=newInnerClassA();int v= inner.x2;}publicclassInnerClassA{int x1= field1;privateint x2= field2;}}
我在外部类中定义了一个默认访问权限(同一个包内的类可以访问)的字段field1, 和一个private权限的字段field2,并且定义了一个内部类InnerClassA,并且在这个内部类中也同样定义了两个和外部类中定义的相同修饰权限的字段,并且访问了外部类对应的字段。最后在外部类的构造方法中我定义了一个方法内变量赋值为内部类中private权限的字段。我们用javac命令(javac InnerClassTest.java)编译这个.java文件,会得到两个.classs文件:
InnerClassTest.class和InnerClassTest$InnerClassA.class,我们再用javap -c命令(javap -c InnerClassTest和javap -c InnerClassTest$InnerClassA)分别反编译这两个.class文件,InnerClassTest.class的字节码如下:
我们注意到字节码中多了一个默认修饰权限并且名为access$100的静态方法,其接受一个InnerClassTest类型的参数,即其接受一个外部类对象作为参数,方法内部用三条指令取到参数对象的field2字段的值并返回。由此,我们现在大概能猜到内部类对象是怎么取到外部类的private权限的字段了:就是通过这个外部类提供的静态方法。
类似的,我们注意到 24 行字节码指令invokestatic,这里代表执行了一个静态方法,而后面的注释也写的很清楚,调用的是InnerClassTest$InnerClassA.access$000方法,即调用了内部类中名为access$000的静态方法,根据我们上面的外部类字节码规律,我们也能猜到这个方法就是内部类编译过程中编译器自动生成的,那么我们赶紧来看一下InnerClassTest$InnerClassA类的字节码吧:
果然,我们在这里发现了名为access$000的静态方法,并且这个静态方法接受一个InnerClassTest$InnerClassA类型的参数,方法的作用也很简单:返回参数代表的内部类对象的x2字段值。
我们还注意到编译器给内部类提供了一个接受InnerClassTest类型对象(即外部类对象)的构造方法,内部类本身还定义了一个名为this$0的InnerClassTest类型的引用,这个引用在构造方法中指向了参数所对应的外部类对象。
最后,我们在 25 行字节码指令发现:内部类的构造方法通过invokestatic指令执行外部类的access$100静态方法(在InnerClassTest的字节码中已经介绍了)得到外部类对象的field2字段的值,并且在后面赋值给x2字段。这样的话内部类就成功的通过外部类提供的静态方法得到了对应外部类对象的field2。