Kotlin 中没有直接的「内部类」关键字 ,而是通过嵌套类 和标记为 inner 的嵌套类(内部类) 区分,这是和 Java 最大的不同,核心区别:是否持有外部类的引用。
一、核心定义(一句话记住)
| 类型 | 关键字 | 持有外部类引用? | 访问外部类成员 | 使用场景 |
|---|---|---|---|---|
| 嵌套类 | 无(直接写在类里) | ❌ 不持有 | 只能访问外部类静态成员(companion 里的) | 独立工具类、和外部类无依赖 |
| 内部类 | 加 inner 关键字 |
✅ 持有 | 可以访问外部类所有成员(包括私有) | 需要依赖外部类数据 |
二、代码示例(最直观)
1. 嵌套类(默认,不加 inner)
kotlin
class Outer {
private val outerVal = "外部类私有成员"
companion object {
const val staticVal = "外部类静态常量"
}
// 嵌套类(默认)
class Nested {
fun test() {
// 错误!无法访问外部类普通成员(不持有引用)
// println(outerVal)
// 正确!可以访问静态成员
println(staticVal)
}
}
}
// 调用方式:直接 外部类.嵌套类
fun main() {
Outer.Nested().test()
}
2. 内部类(加 inner 关键字)
kotlin
class Outer {
private val outerVal = "外部类私有成员"
// 内部类(必须加 inner)
inner class Inner {
fun test() {
// 正确!可以访问外部类所有成员
println(outerVal)
// 显式引用外部类:this@Outer
println(this@Outer.outerVal)
}
}
}
// 调用方式:必须先创建外部类对象
fun main() {
Outer().Inner().test()
}
三、关键区别详解
1. 引用关系(最重要)
- 嵌套类 :相当于 Java 的
static内部类,完全独立,不持有外部类对象,内存上无关联。 - 内部类 :相当于 Java 的普通内部类,强依赖外部类,必须依附外部类对象存在。
2. 创建方式不同
- 嵌套类:
外部类.嵌套类() - 内部类:
外部类对象().内部类()
3. 访问权限不同
- 嵌套类:只能访问外部类的静态成员(companion object 中)。
- 内部类:可以访问外部类所有成员(private、protected、public 都可以)。
4. 内存泄漏风险
- 嵌套类:无内存泄漏风险(无引用)。
- 内部类:有内存泄漏风险(持有外部类引用,比如在 Android 中使用不当会导致 Activity 无法回收)。
四、和 Java 对比(快速对照)
| Kotlin | Java |
|---|---|
| 嵌套类(class) | 静态内部类(static class) |
| 内部类(inner class) | 普通内部类(class) |
五、使用建议
- 优先用嵌套类:如果类不需要访问外部成员,一定用嵌套类(安全、无内存泄漏)。
- 内部类慎用 :只有必须依赖外部类数据时才用
inner。 - 内部类中访问外部类:用
this@外部类名区分(避免同名变量冲突)。
总结
- 不加 inner = 嵌套类:独立、无外部引用、只能访问静态成员、直接创建。
- 加 inner = 内部类:依赖外部类、持有引用、可访问所有成员、必须依附外部对象创建。
- 核心口诀:嵌套无引用,内部靠外部。