本文探讨 Kotlin 和 Java 中的内部类:InnerClass 与嵌套类(Nested Class)的区别、局部类的特点,并通过示例展示如何创建和使用匿名内部类。重点介绍内部类如何访问外部类成员,以及在 Android 中的常见应用场景(如点击监听)。
一、概念对照
| Kotlin |
Java |
说明 |
| 内部类(inner class) |
内部类(非 static) |
使用 inner 关键字修饰,需要通过外部类实例创建;会持有外部类实例引用(注意可能导致内存泄漏)。可访问外部类成员;同名成员用 this@外部类名.xxx 调用。 |
| 嵌套类(nested class) |
静态内部类(static nested class) |
外部类中的 object 单例也是嵌套类(也称“嵌套对象”)。无法直接访问外部类实例成员(除非自己创建外部类实例),但可以访问外部类中其它嵌套类(同为 static)。 |
| 局部类(local class) |
局部内部类 |
定义在方法/代码块内部的类。可访问外部变量(通常是捕获语义),但外部无法直接访问该类。 |
| 匿名内部类(object 表达式) |
匿名内部类 |
Kotlin 访问外部函数局部变量不要求 final(详见 Lambda/闭包语义)。对 SAM(单抽象方法)接口一般用 Lambda 更简洁;当需要重写多个方法时只能用 匿名对象。可访问外部类成员。 |
二、内部类(Inner Class)
class Wai {
val str = "外部"
fun method() { println(str) }
inner class Nei {
val str = "内部"
fun show1() { println(str) } // 打印:内部
fun show2() { println(this@Wai.str) } // 打印:外部
fun show3() { this@Wai.method() } // 打印:外部
fun show4() {
val str = "局部"
println(str) // 打印:局部
}
}
}
Wai().Nei().show1()
Wai().Nei().show2()
Wai().Nei().show3()
Wai().Nei().show4()
三、嵌套类(Nested Class)
class WaiBu {
val str = "外部"
class QianTao1 {
val str = "嵌套1"
fun show1() { println(str) }
}
class QianTao2 {
val str = "嵌套2"
fun show2() { println(str) }
fun show3() {
QianTao1().show1() // 调用另一个嵌套类
}
}
}
WaiBu.QianTao1().show1() // 打印:嵌套1
WaiBu.QianTao2().show2() // 打印:嵌套2
WaiBu.QianTao2().show3() // 打印:嵌套1
四、匿名内部类(object 对象表达式)
1)基础示例:捕获外部局部变量
fun outer() {
var num = 0 // 被捕获的局部变量可以是 var,不强制 final/val
val obj = object {
fun inner() { num += 1 }
}
obj.inner()
}
2)Android 示例:点击监听
fun show(xxx: View) {
var num = 0
// 对象表达式写法(匿名内部类)
xxx.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
num += 1
}
})
// Lambda 简写(仅适用于只有一个抽象方法的 SAM 接口)
xxx.setOnClickListener { _ ->
num += 1
}
}
|