内部类
内部类是定义在另一个类内部的类。Java 支持四种内部类,通过不同的方式实现数据和行为的封装。
为什么需要内部类
大多数情况下,我们把类定义为独立的文件。但有时候,一个类只会被另一个类使用,或者需要访问外部类的私有成员,这时内部类就派上用场了。
比如在 GUI 编程中,按钮和它的点击行为紧密相关;在数据结构中,节点和容器不可分割。内部类让这种「一对一」的关系表达得更自然。
四种内部类一览
┌─────────────────────────────────────────────────────────────────┐
│ 内部类分类 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 内部类 │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ 非静态内部类 │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │ │成员内部类│ │局部内部类│ │匿名内部类│ │ │ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ 静态内部类 │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘快速导航
| 类型 | 特点 | 使用场景 |
|---|---|---|
| 成员内部类 | 依附外部类实例 | 外部类需要访问内部类私有成员 |
| 局部内部类 | 作用域在方法内 | 方法内临时使用,逻辑封装 |
| 匿名内部类 | 没有名字,一次性使用 | 回调、事件监听、临时实现 |
| 静态内部类 | 不依赖外部类实例 | 工具类、紧密关联的数据结构 |
核心区别
| 类型 | 创建方式 | 能访问外部类实例成员吗 |
|---|---|---|
| 成员内部类 | outer.new Inner() | ✅ 能 |
| 局部内部类 | 方法内 new | ✅ 能 |
| 匿名内部类 | 直接 new 接口/抽象类() | ✅ 能 |
| 静态内部类 | new Outer.Inner() | ❌ 不能 |
选型建议
遇到「要不要用内部类」的问题时,可以这样思考:
- 这个类只在另一个类里用? 用成员内部类或静态内部类
- 只用一次? 用匿名内部类(如果是接口/抽象类实现)或局部内部类
- 需要访问外部类实例? 用非静态内部类
- 只是逻辑上归类,没有依赖关系? 用静态内部类
关于内部类的实战应用,可以查看 内部类应用场景。
