笔友城堡 - 可定义的个人主页

前言

简单记录一下Kotlin面试中涉及let相关的知识点,记录于此,方便自己查阅和学习。

顺便对比一下run,apply,also的差异。

正文

let是什么?

let是一个 作用域函数(Scope Function),用于 在对象上下文中执行代码块,并返回 Lambda 的结果。

val result = obj.let {
    it.doSomething()
    123
}

特点

特性说明
上下文对象it
返回值Lambda 的返回值
是否改变原对象不改变
常见用途空安全处理、链式调用

空安全处理

val name: String? = null
name?.let {
    println(it.length)
}
  1. 只有当 name != null时才执行
  2. 避免 if (x != null)的模板代码

为什么不用 if (name != null)

回答:

  1. let更简洁
  2. 自动完成非空分支
  3. 作用域内类型自动转为非空

let 、run、apply对比

函数上下文返回值典型场景
letitLambda 结果空判断、映射
runthisLambda 结果计算、初始化
applythis对象本身对象配置
alsoit对象本身日志、副作用

示例:

val a = user?.let { it.name }        // 返回 name
val b = user?.run { this.name }      // 返回 name
val c = user?.apply { name = "Tom" } // 返回 user
val d = user?.also { log(it) }       // 返回 user

选择哪个函数,取决于你是想“返回对象”还是“返回结果”,以及喜欢 it还是 this

let和run对比

对比点letrun
函数类型(T) -> RT.() -> R
上下文对象itthis
是否可省略不能省可省略
更像普通函数成员函数
val user = User("Tom")
user.let {
    println(it.name)
}
user.run {
    println(name) // 等价于 this.name
}
用 let + it
  • 做 空安全处理
  • 做 数据转换
  • 不想污染作用域
用 run + this
  • 做 对象初始化
  • 多次访问对象属性
user.run {
    name = "Tom"
    age = 18
}

let的返回值陷阱

val x = listOf(1, 2, 3).let {
    it.size
    it
}

返回值是 it 的值

Kotlin中所有代码块都有返回值,最后一个表达式即返回值。

let是否会产生性能问题?

不会

  • let是inline函数
  • 编译期直接展开
  • 无额外对象创建
public inline fun <T, R> T.let(block: (T) -> R): R

let是内联函数,没有运行时开销,适合频繁使用。

什么时候不该用 let?

滥用let导致可读性下降

user?.let {
    it.address?.let {
        it.city?.let {
            println(it)
        }
    }
}

更好的写法:

user?.address?.city?.let {
    println(it)
}

let应提升可读性,而不是嵌套地狱。

小总

let是 Kotlin 中最常用的作用域函数,主要用于 空安全处理和结果映射,通过 it访问对象,返回 Lambda 结果,并且是内联函数,无性能损耗。

参考文章

AI

相关网址

笔友城堡 - 可定义的个人主页

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...