Kotlin作用域函数块是否有效内联?内联类场景疑问
Kotlin inline class与作用域函数的Lambda对象疑问解答
直接结论:你的with(arithmetic)不会创建Lambda对象
Kotlin标准库中的with函数本身是inline函数,它的定义如下:
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
因为block参数被标记为inline,编译器会直接把Lambda里的代码内联到调用位置,不会在堆上生成任何Lambda对象实例。这完全契合你用inline class避免额外对象实例化的设计目标,不用担心作用域函数破坏你的设计。
为什么官方文档称其为Lambda表达式?
文档里的说法是从语法层面出发的——这个代码块确实符合Lambda的语法定义,但inline修饰符改变了它的编译行为:它不再是一个需要实例化的对象,而是直接被展开成调用处的代码片段。
确保作用域函数不产生对象分配的要点
- 优先使用标准库自带的inline作用域函数:
with、run、let、apply、also都是inline的,只要不手动修改它们的实现,就不会有对象创建问题。 - 注意Lambda的捕获逻辑:如果Lambda捕获了外部的非基本类型、非inline类的变量,编译器可能会生成辅助类,但如果只是操作receiver对象(比如你的
arithmetic)或者基本类型,完全不会有额外分配。
针对你的compareTo函数场景
假设你的代码类似这样:
inline class DecimalWrapper(val value: Long) : Comparable<DecimalWrapper> { override fun compareTo(other: DecimalWrapper): Int { return with(arithmetic) { compare(value, other.value) } } }
这里的with代码块会被完全内联到compareTo函数中,不会产生任何额外对象,你的inline class依然能保持零额外实例化的优势。
验证方法
如果还是不确定,可以用IDE的Allocation Tracker工具,或者添加JVM参数-XX:+PrintCompilation来查看编译后的代码,确认没有意外的对象分配。
内容的提问来源于stack exchange,提问作者William Rosenbloom
相关产品推荐
相关产品推荐

