📚 目录
🔍 什么是内部类
内部类(Inner Class) 是定义在另一个类内部的类,主要作用包括:
-
实现代码逻辑的更好封装
-
直接访问外部类的私有成员
-
构建更简洁的回调机制
-
支持多继承的变通实现
🧩 成员内部类
基本语法
class Outer {
private int value = 10;
class Inner {
void print() {
System.out.println("Value: " + value); // 直接访问外部类私有成员
}
}
}
核心特性
-
自动持有外部类实例的引用 (
Outer.this) -
不能定义静态成员(Java 16+ 已允许)
-
实例化方式:
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();
🏗️ 静态内部类
典型实现
class Outer {
static class StaticInner {
void staticMethod() {
System.out.println("Static inner method");
}
}
}
特色对比
| 特性 | 成员内部类 | 静态内部类 |
|---|---|---|
| 外部类引用 | 必须持有隐含引用 | 无隐含引用 |
| 访问外部类成员 | 可直接访问所有成员 | 只能访问静态成员 |
| 实例化方式 | outer.new Inner() | new Outer.StaticInner() |
🔧 局部内部类
方法内部的类
class Outer {
void method() {
final int localVar = 20;
class LocalInner {
void display() {
System.out.println(localVar); // 必须final或等效final
}
}
new LocalInner().display();
}
}
重要特点
-
作用域仅限于定义的方法/代码块
-
自动转化为常规的带编号类文件 (例如:
Outer$1LocalInner.class) -
无法添加访问修饰符
🎭 匿名内部类
经典案例
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked!");
}
});
编译原理
// 实际生成示例
class Outer$1 implements ActionListener {
Outer$1(Outer this$0) {
this.this$0 = this$0;
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked!");
}
}
⚙️ 原理分析
反编译示例
// 成员内部类被编译为独立类
class Outer$Inner {
final Outer this$0;
Outer$Inner(Outer outer) {
this.this$0 = outer;
}
}
🗂️ 使用场景对比
| 类型 | 典型应用场景 | 优点 | 缺点 |
|---|---|---|---|
| 成员内部类 | 迭代器实现、Adapter模式 | 完全访问外部类成员 | 内存泄漏风险 |
| 静态内部类 | 工具类、单例模式 | 不依赖外部实例 | 无法访问非静态域 |
| 局部内部类 | 复杂算法封装 | 限制作用域 | 只能访问final变量 |
| 匿名内部类 | GUI事件处理、简单回调 | 立即实现 | 代码可读性降低 |
❓ 常见问题
Q1:为什么局部内部类只能访问final变量?
当局部内部类访问的局部变量被JVM处理为"捕获变量"时,需要保证其生命周期与内部类实例一致,final保证值不变。
Q2:如何避免内部类内存泄漏?
对非静态内部类持有外部类实例的情况,在使用完毕后显式中断引用:
class Outer {
void createInner() {
Inner inner = new Inner();
// 使用后解除关联
inner.dispose();
}
class Inner {
void dispose() {
outerRef = null; // 手动释放
}
}
}
🏆 最佳实践
-
优先选择静态内部类:除非需要访问外部类实例成员
-
控制内部类可见性:尽可能使用private修饰内部类
-
Lambda表达式替代:Java 8+优先用Lambda代替部分匿名内部类
-
防御性拷贝:返回内部类引用前进行拷贝防御
-
资源释放:对长期存活的内部类实现Closeable接口
1157

被折叠的 条评论
为什么被折叠?



