Kotlin 的 **let
函数是一个常用的 作用域函数,主要用于对对象进行 安全操作或 链式转换。它的核心特点是接收一个对象,通过 lambda 表达式处理该对象并返回结果**。以下是其核心知识点和典型使用场景:
基本特性
- 函数签名:
kotlin
fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
markdown
- 是 `T` 的扩展函数,接收一个以 `T` 为参数的 lambda(`(T) -> R`)。
- 返回 lambda 的结果(类型 `R`),而非原对象本身。
-
核心用途:
- 空安全操作 :配合
?.
避免空指针异常。 - 对象转换:将对象处理后返回新结果。
- 链式调用:在链式操作中处理中间结果。
- 空安全操作 :配合
使用示例
示例 1:空安全操作
scss
val name: String? = getName()
name?.let {
// 仅在 name 非空时执行此块
println(it.toUpperCase()) // it 是 name 的非空副本
it.length // 返回结果类型为 Int
}
示例 2:对象转换
kotlin
val user = User("Alice", 30)
val bio = user.let {
"Name: ${it.name}, Age: ${it.age}" // 转换为字符串
}
println(bio) // 输出 "Name: Alice, Age: 30"
示例 3:链式调用
ini
val result = listOf(1, 2, 3)
.filter { it > 1 }
.let {
it.map { num -> num * 2 } // 处理中间集合
}
// result = [4, 6]
与其他作用域函数的区别
函数 | 参数形式 | 返回值 | 典型场景 |
---|---|---|---|
let |
(T) -> R |
R |
空安全、对象转换 |
apply |
T.() -> Unit |
T |
对象配置(返回自身) |
run |
T.() -> R |
R |
对象计算(直接访问 this) |
also |
(T) -> Unit |
T |
副作用操作(返回自身) |
关键细节
-
**
it
代替对象**:在let
的 lambda 中,原对象通过it
访问(可重命名)。rustkotlinCopy Code user?.let { u -> println(u.name) // 重命名为 u }
-
空安全优化 :结合
?.let
避免嵌套if (obj != null)
。 -
结果导向:适用于需要返回新值的场景(如数据转换、计算)。
典型使用场景
-
空安全检测:
csharpkotlinCopy Code val length = nullableString?.let { it.trim().length // 仅非空时执行 } ?: 0 // 配合 Elvis 操作符提供默认值
-
替代临时变量:
scsskotlinCopy Code // 原始写法 val user = getUser() println(user.name) // 使用 let 简化 getUser()?.let { println(it.name) }
-
链式操作中的中间处理:
scsskotlinCopy Code File("data.txt") .readText() .let { it.trim().split(",") } // 处理读取的文本 .forEach { println(it) }
-
限制变量作用域:
scsskotlinCopy Code val config = loadConfig().let { // 此处处理配置,避免污染外部作用域 validate(it) it.toUpperCase() }
性能说明
let
是内联函数 (inline
关键字),无额外运行时开销。
总结
-
使用
let
的场景:- 需要空安全操作 时(
?.let
)。 - 将对象转换为其他类型时。
- 需要链式处理中间结果时。
- 需要空安全操作 时(
-
避免
let
的场景:- 仅需操作对象本身并返回自身时(用
apply
或also
)。 - 需要直接访问
this
时(用run
)。
- 仅需操作对象本身并返回自身时(用