写在前面
- 在 Kotlin 中,
inner关键字用于声明一个内部类(Inner Class)。内部类是一个嵌套在另一个类中的类,它能够访问其外部类的成员(包括属性和方法)。与普通的嵌套类(nested class)不同,inner类会持有一个对其外部类对象的引用(跟Java中的内部类一样,非静态内部类默认会持有外部类的引用),因此它可以访问和修改外部类的属性和方法。 - Kotlin 中嵌套类是默认静态的,不持有对外部类的引用,无法访问外部类的成员。
两者的选择取决于是否需要访问外部类的成员。如果需要访问外部类成员,选择 inner;否则使用嵌套类(静态内部类)。
Inner类(内部类)
inner 类会持有对外部类的引用,因此可以访问外部类的属性和方法。它比较适用于需要频繁访问外部类成员的场景。
示例:
class OuterClass {
private var outerProperty: String = "I am from OuterClass"
// 使用 inner 声明内部类
inner class InnerClass {
fun accessOuter() {
// 通过 this@OuterClass 引用外部类
println("Accessing from InnerClass: $outerProperty")
}
}
}
fun main() {
val outer = OuterClass()
val inner = outer.InnerClass() // 创建内部类实例
inner.accessOuter() // 调用内部类方法访问外部类成员
}
输出如下:
Accessing from InnerClass: I am from OuterClass
使用场景:
- 事件监听:需要在一个内部类中访问和修改外部类的 UI 或数据。
- 双向交互:当外部类和内部类需要频繁交互,访问彼此的数据时使用
inner类。
嵌套类(静态内部类)
Kotlin 中默认的嵌套类是静态的,也就是说它不持有对外部类的引用,因此不能访问外部类的成员。
示例:
class OuterClass {
private var outerProperty: String = "I am from OuterClass"
// 嵌套类(默认静态)
class NestedClass {
fun showMessage() {
// 无法访问 outerProperty,因为嵌套类不持有对外部类的引用
println("This is a nested class")
}
}
}
fun main() {
val nested = OuterClass.NestedClass() // 创建嵌套类实例
nested.showMessage() // 调用嵌套类方法
}
输出如下:
This is a nested class
使用场景
- 不需要外部类的引用:嵌套类只处理自己的逻辑,不需要访问外部类的成员。例如,工具类、数据处理类等。
- 避免内存泄漏:嵌套类不会持有对外部类(通常是 Activity)的隐式引用,减少内存泄漏的风险。使用示例参见:Kotlin中正确的使用Handler
总结
- Inner 类:适合需要访问外部类成员的场景,但要小心内存泄漏。
- 嵌套类(静态内部类):默认不持有外部类引用,适合不需要外部类成员的场景,静态内部类有助于防止内存泄漏。例如在使用
Handler时,利用静态嵌套类和WeakReference可以有效避免内存泄漏。
| 特点 | Inner 类 | 嵌套类(静态内部类) |
|---|---|---|
| 是否持有外部类引用 | 持有外部类引用,可以访问外部类成员 | 不持有外部类引用,不能访问外部类成员 |
| 用途 | 需要访问外部类的成员 | 不需要访问外部类成员 |
| 使用场景 | 事件监听、UI交互等复杂交互场景 | 工具类、辅助类,避免内存泄漏的场景 |