内部类是Java的类的一种形式,它的使用语法比较奇怪,让一些开发人员不能正确地理解它。那么,内部类和普通的JAVA类有什么区别呢?
先介绍一下内部类的分类和使用方法。
内部类就好像是一只寄生虫一样,生存在其他类的内部。定义在类内部的类就叫做内部类,它缩小了可见性,例如下面的代码:
对于B类来说,它的完整类名就是abc.A.B,命名空间进一步缩小了,并且B对A产生了一种依赖关系,只有A存在的时候B才会存在。
根据内部类的定义结构的不同,可以把内部类分为两种:成员式和局部式。成员式内部类指的是他们定义的地方与成员变量和成员方法类似,
就好像类的一个成员一样。局部式内部类则是定义在方法体中,仅属于局部范围所有。
然后,成员式内部类又可以分为:静态内部类和成员内部类。
局部式又可以分为:普通局部内部类和匿名内部类。
1.静态内部类
使用static关键字修饰的内部类,例如下面的代码:
在外部类加载的时候,静态内部类也随之加载,它的完整类名是abc.Outter.Inner,编译后的class文件名为“Outter$Inner.class”。由于静态内部类是
静态的,所以它无法访问外部类的非静态成员。其实,静态内部类相对于外部类来说,几乎是独立的,它可以在没有外部类对象的情况下,单独创造
一个内部类的对象。
(在某种程度上说,公开的静态内部类就相当于一个普通的类。。)
总结一下:静态内部类相对于外部类来说,仅仅是包含关系,缩小了命名空间,完整类名中多了一个外部类的名称。本质上是两个独立的类,JVM也不知道
它们两个有包含关系。
2.成员内部类
没有使用static关键字修饰的内部类,例如下面的代码:
此时的内部类需要等外部类创建了对象以后才会被加载到JVM中,它属于外部类的某个实例,因此它可以访问外部类的静态和非静态成员。创建
内部成员类的时候,语法比较特殊,首先创建一个外部类的实例,然后用这个实例调用new语句,代码如下:
对于成员内部类的构造方法来说,系统会为它们自动加上一个外部类的参数以及一个外部类的成员变量,这是为了遵循先有外部类实例才能有内部类
实例的原则,代码如下:
class Inner(Outter o){
this.o =o;
}
当内部类访问外部类的成员时,则是通过该自动添加的成员变量进行访问,就好像下面的代码:
o.abc();
3.局部内部类
局部内部类就没有范围的概念了,它仅在定义它的方法中有效,例如下面的代码:
本质上来说,局部内部类它也是一个独立的类,只不过它的一些使用受到了限制,例如,它不能使用static关键字,只能使用final和abstract关键字,仅可以访问外部类
带有final关键字的局部变量,因为它访问的是一个字面量或镜像,该局部变量已经不存在了。但是,它可以访问任意外部类对象的成员变量。
(与成员内部类类似,局部内部类的构造方法也会自动加上一个外部类类型的参数,以及为该内部类加一个外部类型的成员变量。)
当局部内部类定义在静态方法中时就相当于静态内部类。
4.匿名内部类
如果一个局部内部类没有名字,则它就是匿名内部类,例如下面的代码:
在以上代码中,匿名内部类的定义和使用根本没有出现class关键字,但事实上它还是创建了。该类实现了OneInterface接口。它的工作原理相当于局部内部类,只是没有给它
一个名分而已(),外部类也无法直接使用它。