Kotlin中let代码块内return的作用范围:退出let还是外层函数?
问题解答:Kotlin let代码块中return的作用范围
嘿,这个问题刚好戳中了Kotlin里内联函数和return结合的一个容易踩坑的点,先给你明确结论:代码块内的return "TYPE_A"会直接退出外层的getType()函数,而不是仅作为let的返回值赋值给type变量。
为什么会这样?得从let的源码特性说起
先看Kotlin标准库中let函数的源码:
@kotlin.internal.InlineOnly public inline fun <T, R> T.let(block: (T) -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) }
核心点在于let是一个内联(inline)函数。Kotlin里的内联函数会把函数体的代码直接嵌入到调用它的地方,而不是像普通函数那样做方法调用。对于内联函数接收的普通lambda参数(没有crossinline修饰的),lambda里的return是非局部返回——简单说就是,这个return会直接跳出包含该lambda的最外层函数,而不是只跳出lambda本身。
举个直白的例子,你的getType()调用let之后,编译时相当于把let的逻辑展开成这样:
fun getType() : String? { val it = mContent if (!TextUtils.isEmpty(it) && it == "TYPE_1") { return "TYPE_A" // 这里的return直接属于getType() } else { return it // 同样直接属于getType() } // 下面的代码根本到不了 val type = ... if (type == "TYPE_A") { return getType_A() } return type }
这下是不是就清楚了?原来的let代码块里的return直接就成了getType()的返回语句。
你的自定义函数逻辑的问题
回到你的getType()函数,当mContent是"TYPE_1"时,return "TYPE_A"会直接结束整个getType()函数,返回"TYPE_A",后面的val type = ...以及判断type的代码永远不会执行,这大概率和你原本的预期不符。
如果你的需求是把"TYPE_A"作为let的返回值赋值给type,然后继续执行后面的逻辑,你需要用带标签的返回return@let,修改后的代码如下:
fun getType() : String? { val type = mContent.let { if (!TextUtils.isEmpty(it) && it == "TYPE_1") { return@let "TYPE_A" // 仅从let的lambda返回,把值给type } else { return@let it // 同样仅返回给type } } if (type == "TYPE_A") { return getType_A() } return type }
这样,let的返回值会被正常赋值给type,后续的判断逻辑也能按预期执行。
最后再划个重点
- 对于内联函数的普通lambda参数,lambda里的
return是非局部返回,直接退出外层包含函数; - 如果只想从lambda本身返回,必须用带标签的返回
return@函数名(比如return@let、return@run); - 只有当lambda是
crossinline修饰的内联函数参数时,才不能用非局部返回,只能用标签返回。
内容的提问来源于stack exchange,提问作者lannyf
相关产品推荐
相关产品推荐

