![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=1738921909-wQSpQN1niGSzD6Q3iJsOhn4OO681u1uu-0-8941624ed21752866f6db40585ef17ec)
扫码看视频
当我们创建一个内部类的对象时,它就拥有了与外部类对象之间的一种联系,这是通过一个特殊的this引用形成的,使得内部类对象可以随意地访问外部类中的所有成员。图7-1展示了这一过程。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_5.jpg?sign=1738921909-7rG0dXP6K92N1So1H8LPrv3XLUe8H6VN-0-3ad08d448e0159f4a960eca146194041)
图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=1738921909-P9NQ1a3hHzSkCMewGHjRCB6rsyESq4fC-0-95b2b3f6f22b763320cb194670b257b5)
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_7.jpg?sign=1738921909-bBzdrsT8Mh8fNqVCp4gbyFBgP1mAvmb4-0-cf9978ce2534e3c151fc975797954c55)
在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=1738921909-laKY3dxaE0iGcDW7HNw0OHz1rmAbMsKs-0-b635bbb16fda30ae3e7cc193bd6844bb)
如果在外部类之外访问内部类,那么可以把外部类名称看成是名称空间,采用“外部类名称.内部类名称”的形式来引用内部类,如果内部类有多层嵌套,那么一一加上其外围类的名称即可,如上述代码7.3所示。
编译Outer.java,编译器提示如图7-2所示的错误。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_9.jpg?sign=1738921909-j8t0nYPNGYtOu3NxMP3RFYW7apFNB109-0-c79c25778ef278b55f31bda4d3f84da1)
图7-2 创建内部类的对象报错
这个错误是什么意思呢?前面刚说了,内部类之所以可以随意访问外部类的成员,其原因在于内部类对象被创建时,会自动建立与外部类对象的一种联系,这种联系首先需要外部类的对象存在才可以建立。现在我们直接创建内部类对象,根本不存在外部类对象,怎么去建立这种联系呢?自然要报错了。
若要创建内部类对象,则需要先创建外部类对象,我们修改代码7.3,先创建外部类对象,如代码7.4所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_10.jpg?sign=1738921909-VU9tgytYd4BfWpLJfhR9n06VdecvSCVq-0-b5a1cf0c53764b3280801bb40309b21d)
有没有觉得这段代码很奇怪,其分别创建了三个类的对象,难道这三个类的对象就自动建立联系了吗?答案是否定的,编译上述代码,依然会出现如图7-2所示的错误。
由于内部类对象需要与外部类对象建立关联,因此内部类对象必须通过外部类对象来创建,这样才能建立联系,而不是简单地new。要建立这种联系,需要使用“外部类对象.new 内部类名称([构造方法参数列表])”这种特殊的语法形式来创建内部类对象。
修改代码7.4,如代码7.5所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_11.jpg?sign=1738921909-wtHgF1znCLANPnGIyp2O8s3dUfzunVQk-0-25eb646d63dce0b6787b951922a56ebf)
在.new之后,不需要再添加外部类的名称了,因为前面已经有类型的完整名称了。
编译Outer.java,一切正常,执行Test类,输出结果如下:
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_12.jpg?sign=1738921909-BoDZ2ksolYcHFa3YQZlmp89KyfHqTTFJ-0-d31bb25143be6b795d22a497641d7de8)
可以看到内部类对象的创建是比较麻烦的,不过读者不用担心,在实际开发中,如果需要在外部用到内部类对象,则一般由外部类给出一个获取内部类对象的方法。这不仅可以简化内部类对象的创建,还可以对外屏蔽内部类对象的创建细节。
修改代码7.5,如代码7.6所示。
![img](https://epubservercos.yuewen.com/AD1899/18685354708165706/epubprivate/OEBPS/Images/txt007_13.jpg?sign=1738921909-i3CiEdEZvdOiHmWPqrPEVf1dgiLgKK5M-0-7d37b5a7bb2767b97ac68342776ab1d8)
在Middle类中给出了获取Inner类对象的方法,在Outer类中给出了获取Middle类对象的方法,于是在main方法中的代码就变得熟悉而亲切了。