![Java无难事:详解Java编程核心思想与技术](https://wfqqreader-1252317822.image.myqcloud.com/cover/59/35011059/b_35011059.jpg)
7.2 访问外部类
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_4.jpg?sign=1739525765-Hm2KyKhn902w6J6s88na1LWugSU3q2zd-0-db91ea1a2db9b5e53a85e1d5925cf9f0)
扫码看视频
当我们创建一个内部类的对象时,它就拥有了与外部类对象之间的一种联系,这是通过一个特殊的this引用形成的,使得内部类对象可以随意地访问外部类中的所有成员。图7-1展示了这一过程。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_5.jpg?sign=1739525765-nuhoOa8MfGBubEisgRtjukb2Mvohj7mi-0-ea573819130ab58bf14f658f2b20f119)
图7-1 内部类对象可以访问外部类的成员的原理图
注意图中的Outer.this,在内部类中访问外部类的成员,可以通过“外部类名称.this”的形式来获得外部类对象的引用。代码7.1中Inner类的print方法内部访问外部类的实例变量index,也可以通过Outer.this.index的方式来访问。当然,在一般情况下,不需要这么麻烦,因为这种关系是隐含建立的,所以不需要显式地去使用“外部类名称.this”的方式来访问外部类成员。不过当内部类中的成员和外部类中的成员重名时,或者内部类有多层嵌套时,就需要使用“外部类名称.this”这种方式来显式地指定访问的是哪一个成员。我们看代码7.2。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_6.jpg?sign=1739525765-08xmPFIPe0kJH5kcAiMma4y8qXArF8in-0-c702e1d44b5adceb38a4ea98b26bf9cd)
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_7.jpg?sign=1739525765-3aTFCZN00FA4vM92yAmdkF5JNR8yOWbL-0-1ee2d5bbe5d29ad3c19bec5828002628)
在Outer类中定义了一个内部类Middle,在Middle类中还有一个内部类Inner,这三个类都有一个同名的实例变量index,在Inner类的print方法中,为了明确访问的是哪一个index,我们需要使用“外部类名称.this”的形式来指定引用的变量。
接下来我们想看看代码7.2运行的结果,这时就牵涉如何创建内部类的对象了。代码7.1的Inner类对象是在外部类Outer的print方法中创建的,如果我们想在外部类之外直接创建内部类的对象是否可以呢?修改代码7.2,在Test类的main方法中添加直接创建Inner类对象的代码,如代码7.3所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_8.jpg?sign=1739525765-bbYYQuqescN1ff1fMnw2a9P42h8ZCrdu-0-8cdec1a85804a9a6b9af0e82a7a0c012)
如果在外部类之外访问内部类,那么可以把外部类名称看成是名称空间,采用“外部类名称.内部类名称”的形式来引用内部类,如果内部类有多层嵌套,那么一一加上其外围类的名称即可,如上述代码7.3所示。
编译Outer.java,编译器提示如图7-2所示的错误。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_9.jpg?sign=1739525765-P4b7ElUraErPFw8EZcajjABA8yHjCbY7-0-dfe02438635841e139d34f2ecc88d417)
图7-2 创建内部类的对象报错
这个错误是什么意思呢?前面刚说了,内部类之所以可以随意访问外部类的成员,其原因在于内部类对象被创建时,会自动建立与外部类对象的一种联系,这种联系首先需要外部类的对象存在才可以建立。现在我们直接创建内部类对象,根本不存在外部类对象,怎么去建立这种联系呢?自然要报错了。
若要创建内部类对象,则需要先创建外部类对象,我们修改代码7.3,先创建外部类对象,如代码7.4所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_10.jpg?sign=1739525765-HTSGuioGZsHrCNSCl2L2k7mDiNHAjKid-0-f92cbf81b1a72a71b2818059fcbe3951)
有没有觉得这段代码很奇怪,其分别创建了三个类的对象,难道这三个类的对象就自动建立联系了吗?答案是否定的,编译上述代码,依然会出现如图7-2所示的错误。
由于内部类对象需要与外部类对象建立关联,因此内部类对象必须通过外部类对象来创建,这样才能建立联系,而不是简单地new。要建立这种联系,需要使用“外部类对象.new 内部类名称([构造方法参数列表])”这种特殊的语法形式来创建内部类对象。
修改代码7.4,如代码7.5所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_11.jpg?sign=1739525765-wUV4Z4j1gu2tGsvo8uA8oNqyWbwcynvC-0-6452c29671584a145bdee1b1cc136a08)
在.new之后,不需要再添加外部类的名称了,因为前面已经有类型的完整名称了。
编译Outer.java,一切正常,执行Test类,输出结果如下:
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_12.jpg?sign=1739525765-7YCIM3CRGJVyvlzFxenMK9WU3vEzyswY-0-098865492b0f3649c7c7c328c2be0dcc)
可以看到内部类对象的创建是比较麻烦的,不过读者不用担心,在实际开发中,如果需要在外部用到内部类对象,则一般由外部类给出一个获取内部类对象的方法。这不仅可以简化内部类对象的创建,还可以对外屏蔽内部类对象的创建细节。
修改代码7.5,如代码7.6所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_13.jpg?sign=1739525765-du1V679ovG6KF2r1NidHlDg76Y1RSdvd-0-be7e07c7ca88fc9f158eab3da5957c24)
在Middle类中给出了获取Inner类对象的方法,在Outer类中给出了获取Middle类对象的方法,于是在main方法中的代码就变得熟悉而亲切了。