kotlin 内联函数 inline
一、当函数被声明为内联函数(函数的前缀增加inline),那么函数体会被直接替换到函数被声明的地方,而不是被正常的调用。如下的代码
inline fun synchronized(lock: Lock, action: () -> Unit) { lock.lock() try { return action() } finally { lock.unlock() } } fun foo(l: Lock) { println("before sync") synchronized(l) { // 这里的函数会被替换成synchronized的代码 println("Action") } println("after sync") }
咱们可以看转化成java的foo函数(这里把一些无关的判断去掉)
public static final void foo(@NotNull Lock l) { System.out.println("before sync"); l.lock(); try { int var2 = false; System.out.println("Action"); } finally { l.unlock(); } System.out.println("after sync"); }
如上所述,直接将synchronized 替换到了foo本地
二、当inline函数赋值给临时变量,那么该临时变量不再具有inline的特性
val l = ReentrantLock() val syn = ::synchronized syn(l) { println("test") }
如上是kotlin的先赋值给临时变量的操作,对应的java解码是
ReentrantLock l = new ReentrantLock(); KFunction syn = (KFunction)null.INSTANCE; ((Function2)syn).invoke(l, null.INSTANCE);
如上,调用通用函数的调用invoke的方式
具体的解释是:synchronized被临时变量保存起来,以便后面的使用。 官方语言:lambda表达式的代码将不能被内联,因为必须要有一个包含这些代码的对象存在
三、关于inline函数的传递
正常参数如果被直接调用或者作为参数传递给另外一个inline函数,该参数是可以被内联。
如一中所述:lambda默认是inline函数,所以在传入synchronized的时候也被当作内联函数继续被解析
当禁止传入的函数也被内联,则可以对该函数参数使用noinline
inline fun synchronized(lock: Lock, noinline action: () -> Unit) { lock.lock() try { return action() } finally { lock.unlock() } } // 则对应的foo函数的代码则为 public static final void foo(@NotNull Lock l) { System.out.println("before sync"); Function0 action$iv = (Function0)null.INSTANCE; l.lock(); try { action$iv.invoke(); // 这里使用的是函数的调用 } finally { l.unlock(); } System.out.println("after sync"); }
如上所述,使用的是invoke,而不是inline特性的替换
四、使用inline的时候注意函数不宜太过复杂或者太长,因为会被替换到本地从而增加了字节码的长度。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!