Kotlin 标准库函数 run、apply、let、also、with 简单对比。
主要是太容易忘记了,因此记录于此。(AI整理)
这五个函数本质上都是作用域函数(Scope Functions),区别只在于三点:
是不是扩展函数
对象怎么引用(
it/this)返回什么(对象本身 / Lambda 结果)
只要抓住这三点,就不会再混淆。
正文
下面依次介绍怎么使用。
let
inline fun <T, R> T.let(block: (T) -> R): R特点
对象作为参数传入:
it返回 Lambda 的最后一行
非常适合空安全处理
示例 1:空安全处理
val list: List<Int>? = arrayListOf(1, 2, 3) list?.let { println(it.size) it.map { value -> value * 2 } }
示例 2:数据转换 / 映射
val name: String? = "Kotlin" val length = name?.let { it.length } println(length) // 6
示例 3:链式转换
val result = "123" .let { it.toInt() } .let { it * 2 } println(result) // 246
适用场景
object?.let { }判空数据转换 / 映射
限制变量作用域
run
inline fun <T, R> T.run(block: T.() -> R): R特点
this访问对象(可省略)返回 Lambda 结果
=
with+let的结合体
示例 1:基本使用
val result = "biumall.com".run { println(isEmpty()) length } println(result) // 8
示例 2:空安全 + 组合属性
data class User(val firstName: String, val lastName: String) val user: User? = User("Kotlin", "Dev") val fullName = user?.run { "$firstName $lastName" } println(fullName) // Kotlin Dev
示例 3:链式处理
val size = listOf(1, 2, 3) .run { filter { it > 1 } } .size println(size) // 2
适用场景
对对象进行计算
需要返回值
想避免
it,又想判空
val name = user?.run { "$firstName $lastName" }with
inline fun <T, R> with(receiver: T, block: T.() -> R): R特点
不是扩展函数
对象作为参数传入
this访问对象返回 Lambda 结果
示例 1:基本使用
val student = Student("大神", 20) val result = with(student) { println(name) println(age) 91 }
示例 2:Android 常见写法
with(textView) { text = "Hello" textSize = 16f setTextColor(Color.BLACK) }
示例 3:计算结果
data class Person(val name: String, val age: Int) val person = Person("Tom", 18) val score = with(person) { if (age > 16) 100 else 60 } println(score) // 100
适用场景
对同一个对象多次访问属性/方法
Android 中
RecyclerView.onBindViewHolder很常见
缺点:不支持空安全调用(
?.with {}不存在)
apply
inline fun <T> T.apply(block: T.() -> Unit): T特点
this访问对象始终返回对象本身
非常适合「配置对象」
示例 1:集合初始化
val list = ArrayList<Int>().apply { add(1) add(2) add(3) }
示例 2:View 配置
val textView = TextView(context).apply { text = "Hello" textSize = 16f setTextColor(Color.BLACK) }
示例 3:对象构建
data class User(var name: String = "", var age: Int = 0) val user = User().apply { name = "Kotlin" age = 10 }
典型场景
对象初始化
Builder 模式简化
View / Model 配置
val textView = TextView(context).apply { text = "Hello" textSize = 16f setTextColor(Color.BLACK) }
also
inline fun <T> T.also(block: (T) -> Unit): T特点
使用
it指代对象返回对象本身
不影响主流程,只「顺手做事」
示例 1:打印日志
val name = "biumall.com".also { println("长度:${it.length}") }
示例 2:链式调用中插入副作用
val user = getUser() .also { logUser(it) } .apply { saveToDb(this) }
示例 3:调试 / 埋点
val file = File("test.txt") .also { println("文件路径:${it.path}") } .also { it.createNewFile() }
典型场景
日志 / 埋点
调试
链式调用中插入副作用
val user = getUser() .also { logUser(it) } .apply { saveToDb(this) }
小结
想改对象用 apply,想顺手做事用 also,想算结果用 run,想判空处理用 let,想少写对象名用 with。
| 函数 | 是否为扩展函数 | 对象引用 | 返回值 | 典型用途 |
|---|---|---|---|---|
let | 是 | it | Lambda 结果 | 判空、映射、链式转换 |
run | 是 | this | Lambda 结果 | 对象计算、结果返回 |
with | 否 | this | Lambda 结果 | 对同一对象多次操作 |
apply | 是 | this | 对象本身 | 对象初始化、配置 |
also | 是 | it | 对象本身 | 链式调用、日志、埋点 |
《》

