嵌套类
- 静态嵌套类,类前面有static修饰符
- 非静态嵌套类,又称内部类
- 普通内部类
- 局部内部类
- 匿名内部类
public class Main {
// 静态嵌套类
static class Inner1{ }
/* 包内静态内部类的好处:
1. 作用域不会扩散到包外
2. 可使用 外部类.内部类 方式直接访问
3. 内部类可以直接访问所有静态属性及方法
*/
// 普通内部类
class Inner2{}
public void f(){
// 局部内部类
class Inner3{}
// 匿名内部类
new Object(){};
}
}
使用理由
- 细粒度访问控制
- 避免过多类定义
匿名内部类
- 没有正式类名
- 没有构造函数
- 可以继承、改写、增加父类的方法
- 不能定义静态成员(静态常量除外)
- 可以访问外部类的成员
局部内部类
- 编译后名称:外部类名+$+序号+内部类名
- 可以继承其他类,或者实现其他接口
- 非静态的类,不能包含静态成员(变量和方法),除了常量
- 可以访问外部包围类的成员
- 如果定义在静态方法中,只能访问包围类的静态成员
- 局部内部类不能是一个接口,即接口不能定义在代码块中
普通内部类
- 编译后名称:外部类名+$+内部类名
- 可以继承其他类,或者实现其他接口
- 可以用private/package private(不写)/protected/public控制外界访问
- 非静态的类,不能包含静态变量/方法,除了常量
- 和外部包围类的实例相关,一个普通内部类实例肯定是在一个外部包围类的实例中,且可以访问外部包围类的所有成员
- 在第三方类中,需要先创建外部包围类实例,才能创建普通内部 类的实例,不允许单独的普通内部类对象存在!!!
静态嵌套类
- 需要加修饰符static
- 可以定义静态成员和非静态成员
- 不能直接访问包围类的非静态成员,可直接访问包围类的静态成员
- 可通过包围类的对象进行访问非静态成员
- 外界可以通过静态嵌套类名访问其静态成员,通过对象访问其非静态成员
- 外界需要通过包围类才可以访问到静态嵌套类,并创建其对象,不需要外部包围类的实例
对比
变量遮蔽
- 以离得近作为优先原则
- 优先级高的变量会遮蔽优先级低的变量
- 外部包围类.this.变量名,可以访问到外部包围类的成员变量
- 静态嵌套类不能访问非静态变量
- Java 7及以前,匿名内部类和局部内部类只能访问外部包围类的final成员变量
- Java 8及以后,匿名内部类和局部内部类可访问外部包围类的final成员变量和 事实意义上的final变量(effectively final, 一个变量定值后,再也没有改过值)
应用
- 匿名内部类
- 无需类名,用过即焚,使用广泛
- 该类的对象只要一个,且方法只有一个,代码短
- Android中常用匿名内部类
- 局部内部类
- 定义在方法体内,只能在当前方法内使用,代码短
- 使用较少
- 介于匿名内部类和普通内部类之间
- 迭代器
- 普通内部类
- 广泛使用在具有母子结构的类,内部类对象和外围类保持联系
- 如Map和Map.Entry,ZipFile和ZipFile.ZipEntryIterator等
- 静态嵌套类
- 和外围类没有太多的联系
- 节省普通内部类和外围类的联系开销
- 使得外围类对象更容易被垃圾回收器回收