引子:最近几天一直在看内部类,虽然自己用了java将近2年了,但是基本很少使用过内部类,除了有一次在学习android的时候,写过一些外,基本是没有使用的。说实话,个人感觉内部类很是复杂,有时候就图方便,直接用普通的类去完成任务了,也没有去考虑使用内部类这个东西。但是用不用是一回事,学不学又是另外一回事,至少要掌握,说的小点,在笔试,面试什么的有帮助。说的大点,以后遇到需要使用,或者别人写的代码,就可以无压力对待了。
今天主要介绍下最基本的成员内部类。先看个demo。
public class Out { //内部类 private int j = 0; private class Inner{ public int i=1; public void f(){ System.out.println(j); } } public Inner inner(){ return new Inner(); } public static void main(String[] args) { Out out = new Out(); out.j= 2; Out.Inner inner = out.inner(); inner.f(); } }
?
? 上面的例子是个很简单的内部类,Out是类(可以称为外部类),inner是内部类。我们把内部类定义作为类的一个成员的内部类称为“成员内部类”。
代码中我们看到我们使用 returnInner()这个方法去实例化了一个内部类对象,然后在main中去引用了这个对象。看似简单,但是疑问不少。疑问一:为什么要在一个方法体里面实例化内部类,直接实例化不行么?Out.Inner ?inner = new Inner();;疑问二:为什么在main方面里面声明内部类要加上 Out.Inner,直接inner不行么?带着这些疑问我们在eclipse测试下。
?
public static void main(String[] args) { Out out = new Out(); Out.Inner inner = new Inner();//error code System.out.println(inner.i); }
?
public static void main(String[] args) { Out out = new Out(); Inner11 inner = out.inner(); System.out.println(inner.i); }
? 第一个测试报错了,显然,我们无法直接在一个静态的方法中去实例化内部类,必须要使用外部对象是实例化内部对象。
第二个测试正确了,说实话吧,《think ?in java》第四版中文版中有这么一句话:如果想从外部类的非静态方法之外的任何位置创建某个内部类的对象,必要具体的指明 这个对象的类型 OutClassName.InnerClassName(《think in java》第四版中文版347页)。我开始以为这句话没问题,以为必须要加上OutClassName,可是我测试的结果是没有加上OutClassName并没有报错,所以我这里个人认为是否是书中翻译错误或者是我理解错误,请知道的高手帮忙解释下这句话。
那么我就只看第一个错误的原因,就是成员内部类的初始化必须是由外部类的对象去完成这个工作。所以在main方法里面创建一个Out对象,也正是这个Out对象建立起了内部类和外部类的联系,正是这种联系,所以在内部类中是可以使用外部类的任何东西,包括声明是private的内容,这也是为什么,内部类中f()打印的是2而不是0,因为内部类和外部类中间的联系是通过外部类的一个对象的引用,也就是out,所以内部类访问外部类的东西,其实是访问这个引用里面的东西。
最后说下this.和new.的用法,先介绍下.new,其实也很简单,就是在初始化的内部类的时候,直接使用new 关键字处理,Inner inner = out.new Inner()。this的话,是指在内部类中生成对外部类的引用,例如 Out.this就是引用了外部类。
请注意,这里所有的情况都是针对于成员内部类,至于其他的静态内部类,方法内部类,将会在后面的文章中讲到,东西不在乎多,在乎精,在乎理解成自己的东西,think in java厚厚的一本,加上是国人翻译的,如果不去理解的话,那些晦涩难懂的翻译会让你头疼的。
在前面的一篇文章中我们提到过,一个class一定会生成一个class文件,内部类也不例外,它也会生成一个Out$Inner.class的class文件。
内部类始终还是一个类,它也具有一些类的基本特性,这里先介绍到这里,下节介绍方法内部类。