大部分时候,类被定义为一个独立的程序单元。在某些情况下,也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就叫做内部类(也叫嵌套类),包含内部类的类也被称为外部类(也叫宿主类)。Java从JDK1.1开始引入内部类。内部类主要有以下几个作用:
- 内部类提供了更好的封装,可以把内部类隐藏在外部类只内,不允许同一个包中的其他类访问该类。比如,CowLeg类和Cow类,CowLeg在离开Cow以后没有任何意义,这种情况下就可以把CowLeg类定义在Cow类之中,不允许其他类访问。
- 内部类可以直接访问外部类的私有数据,因为内部类作为外部类的成员。但外部类不能访问内部类的实现细节,比如内部类的成员变量。
- 匿名内部类只需要适合创建那些仅需要使用一次的类。
内部类与外部类还有如下两点区别:
- 因为内部类作为外部类的成员,因此多了三个修饰符:private、protected、static。
- 非静态内部类不能拥有静态成员。
内部类定义语法非常简单:
public class OuterClass
{
// 此处可定义内部类
}
内部类可以定义在外部类里面的任何地方,甚至在方法中也可以定义内部类(此时内部类称为局部内部类)。
大部分时候都是将内部类作为外部类的成员内部类进行定义的,而不是作为局部内部类。成员内部类是一种与成员变量、方法、构造器和初始化块相似的类成员;局部内部类与匿名内部类不是类成员。
成员内部类分为两种:静态内部类与非静态内部类(即是否使用static修饰符修饰
经常看到一个java源文件内定义了多个类,那种情况不是内部类,依然是两个相互独立的类,例如下面的程序:
// 下面A、B两个类互相独立,没有谁是谁的内部类
class A(){}
public class B{}
一、静态内部类
用static修饰的内部类就是静态内部类,这个内部类就属于外部类本身,而不属于外部类的某个对象。
根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的实例成员。
静态内部类可以包含静态成员,也可以包含非静态成员。
二、非静态内部类
没有通过static修饰符修饰的内部类称为非静态内部类。非静态内部类的对象必须寄生在外部类对象里,而外部类对象则不一定有非静态内部类对象寄生其中。换句话说,如果存在一个非静态内部类对象,则一定存在一个被它寄生的外部类对象。但外部类对象存在时,外部类对象里不一定寄生了非静态内部类对象。因此外部类对象访问非静态内部类成员时,可能这个非静态内部类对象根本不存在!而非静态内部类访问外部类成员时,外部类对象一定存在。
根据静态成员不能访问非静态成员的规则,外部类的静态方法、静态初始化块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等。
Java不允许非静态内部类里定义静态成员(静态成员变量、静态初始化块、静态方法)。非静态内部类里不能有静态初始化块,但可以包含普通初始化块。非静态内部类普通初始化块的作用与外部类初始化块的作用完全相同。