1.inline的作用

1.1 可以将函数体直接复制到函数调用处

package com.example.kotlinsyntax._inlineclass InlineClass {//inline标记的函数inline fun doInline() {print("inline")}//普通函数fun doNoInline() {print("noInline")}//调用处函数fun test() {doInline()doNoInline()}
}

上面是测试用的原函数,分别是一个inline函数,一个普通,一个负责调用这2个函数的测试函数,看下编译的字节码

package com.example.kotlinsyntax._inline;import kotlin.Metadata;@Metadata(mv = {1, 1, 16},bv = {1, 0, 3},k = 1,d1 = {"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0002\b\u0003\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\t\u0010\u0003\u001a\u00020\u0004H\u0086\bJ\u0006\u0010\u0005\u001a\u00020\u0004J\u0006\u0010\u0006\u001a\u00020\u0004¨\u0006\u0007"},d2 = {"Lcom/example/kotlinsyntax/_inline/InlineClass;", "", "()V", "doInline", "", "doNoInline", "test", "kotlinsyntax"}
)
public final class InlineClass {public final void doInline() {int $i$f$doInline = 0;String var2 = "inline";boolean var3 = false;System.out.print(var2);}public final void doNoInline() {String var1 = "noInline";boolean var2 = false;System.out.print(var1);}/*** 函数调用处*/public final void test() {int $i$f$doInline = false;   // 1String var3 = "inline";      // 2boolean var4 = false;        // 3System.out.print(var3);      // 4this.doNoInline();           // 5}
}

可以看到test函数内部1~4和doInline函数体完全一致,证实了函数体被直接复制到了调用处,5处是doNoInline的调用,可以发现没有讲函数体复制过去

这样可以减少一个调用栈的产生,但是这种优化及其微小,而且如果inline函数体很大,调用他的地方有很多,这样还会产生更多的字节码,使最终产生的文件变大,那他真正的作用在哪里呢?

1.2 inline优化高阶函数调用

如果一个函数包含一个函数类型参数,比如

//参数func 是一个函数类型
fun advancedFunction(func: () -> Unit) {func()
}

kotlin在实现这个函数调用实际是为这个func函数创建一个函数对象,然后调用这个函数对象的invoke方法

public final class InlineClass {public final void doInline() {int $i$f$doInline = 0;String var2 = "inline";boolean var3 = false;System.out.print(var2);}public final void doNoInline() {String var1 = "noInline";boolean var2 = false;System.out.print(var1);}public final void advancedFunction(@NotNull Function0 func) {Intrinsics.checkParameterIsNotNull(func, "func");func.invoke();}public final void test() {int $i$f$doInline = false;String var3 = "inline";boolean var4 = false;System.out.print(var3);this.doNoInline();this.advancedFunction((Function0)null.INSTANCE);}
}

可以看到生成的字节码,jvm为我们创建了Function0函数对象,最终调用func.invoke实现原函数调用。

如果advancedFunction函数是在循环中被调用呢?

while(true) {advancedFunction({ xxx })
}

那就意味着这时候会频繁创建新的函数对象,我们在自定义View的时候都知道要避免的onMeasure和onDraw中创建对象,这样有可能造成内存抖动。如何避免这种情况发生呢,inline就可以发挥作用了

inline函数可以将自身和自身的函数参数都内联化,也就是将自身和自身的函数参数都复制到调用处,我们先讲上面的函数改为内联

class InlineClass {inline fun doInline() {print("inline")}fun doNoInline() {print("noInline")}inline fun advancedFunction(func: () -> Unit) {print("advanced")func()}fun test() {doInline()doNoInline()advancedFunction { print("func") }}
}

查看生成的字节码

//去除了doInline和doNoInline的代码
public final class InlineClass {public final void advancedFunction(@NotNull Function0 func) {int $i$f$advancedFunction = 0;Intrinsics.checkParameterIsNotNull(func, "func");String var3 = "advanced";boolean var4 = false;System.out.print(var3);func.invoke();}public final void test() {int $i$f$advancedFunction = false;$i$f$advancedFunction = false;var3 = "advanced";        // 1var4 = false;             // 2System.out.print(var3);   // 3int var5 = false;         // 4String var6 = "func";       // 5boolean var7 = false;      // 6System.out.print(var6); // 7}
}

可以看到1~3和advancedFunction原函数代码一致
5~7并不再是之前的this.advancedFunction((Function0)null.INSTANCE);
而是将func函数内部的print函数代码复制了过来,这样就有效避免了重复创建对象,inline对这种情况进行了极大的优化

小结:inline可以弥补kotlin在高阶函数实现上的缺陷(对象创建)

Kotlin中的inline作用相关推荐

  1. Kotlin 中infix,inline,noinline,crossinline ,refied 等的理解

    1. infix 的作用 infix 标示的函数可以使用中缀表示法, 中缀表示法就是在写法上可以忽略 . 与 ()并且必须满足三个条件 必须是成员函数或者扩展函数 必须只有一个参数 其参数不能有可变参 ...

  2. 教你如何完全解析Kotlin中的注解

    简述: 从这篇文章将继续开始探索Kotlin中的一些高级的内容,之前有着重探讨了Kotlin的泛型以及泛型型变等内容.现在我们一起来看下Kotlin中的注解.Kotlin中的注解是100%与Java注 ...

  3. 教你如何攻克Kotlin中泛型型变的难点(下篇)

    简述: 前几天我们一起为Kotlin中的泛型型变做了一个很好的铺垫,深入分析下类型和类,子类型和子类之间的关系.什么是子类型化关系以及型变存在的意义.那么今天将会讲点更刺激的东西,也就是Kotlin泛 ...

  4. [译]带你揭开Kotlin中属性代理和懒加载语法糖衣

    翻译说明: 原标题: How Kotlin's delegated properties and lazy-initialization work 原文地址: https://medium.com/t ...

  5. Kotlin中let、run、with、apply及also的差别

    /   今日科技快讯   / 近日,微软刚刚发布了新版操作系统Windows 11,包括全新的设计和诸多新功能,并且能够直接运行安卓应用.该公司首席执行官兼董事长萨蒂亚·纳德拉随后接受媒体专访,他称希 ...

  6. 教你如何攻克Kotlin中泛型型变的难点(应用篇)

    简述: 这是泛型型变最后一篇文章了,也是泛型介绍的最后一篇文章.顺便再扯点别的,上周去北京参加了JetBrains 2018开发者日,主要是参加Kotlin专场.个人感觉收获还是挺多的,bennyHu ...

  7. c语言头文件中定义inline static相关函数的优劣

    头文件中常见static inline函数,于是思考有可能遇到的问题,如头文件经常会被包含会不会产生很多副本?网上说法不一.于是自己验证.经过arm-none-eabi-gcc下测试后得出结论. in ...

  8. 理解 Kotlin 中的属性(property)

    这篇文章是一时兴起想写的,因为我发现我对Kotlin的属性理解一直有误 Java 中的属性是什么(property) 首先我们要搞清楚在 Java 中属性是什么,在 Java 中类的属性不是指一个字段 ...

  9. Kotlin 中的 run、let、with、apply、also、takeIf、takeUnless 语法糖使用和原理分析

    这些Kotlin的语法糖函数经常用,但也很容易搞混,所以转载一下,若混了可以回来再看 转载自公众号:纸上浅谈 正文: 在 Kotlin 有一些可以简化代码的语法糖,比如 run.let.with.ap ...

最新文章

  1. Python 参考手册
  2. centos sudo不能运行_如何在 Linux 中配置 sudo 访问权限 | Linux 中国
  3. Exchange2003 OWA访问,IIS权限设置
  4. Windows系统下多显示器模式开发
  5. Linux优化之IO子系统监控与调优
  6. html输入支付密码样式,基于JS实现类似支付宝支付密码输入框
  7. “微软高管”拯救必应 搞定盖茨成为合伙人?官方打脸:实为开除员工
  8. asp脚本和php脚本,有经典ASP的缓存脚本吗?
  9. 信用指數旁的星星表示什麼?
  10. 为ASP.NET MVC Client-side Resource Combine 添加中文支持
  11. JavaScript网页开发--三.CSS(级联样式表)
  12. 开源项目:使用CUDA NV12转JPG
  13. Echarts 环图 颜色渐变、灰色背景、自适应
  14. easyui radiobutton
  15. python安装报错error: pybind11 2.10+ requires MSVC 2017 or newer
  16. excel表格内文字怎么换行_Excel单元格内如何换行,这几招快拿小本本记下来
  17. 教你微信对接图灵机器人
  18. 状态同步和帧同步的优缺点
  19. 基于网页网站在线视频点播系统 毕业设计毕设源码毕业论文开题报告参考(3)网站后台系统管理功能
  20. 微信小程序在iOS端,出现SSL错误,无法建立安全连接的问题解决

热门文章

  1. html 设置textarea字体颜色,textarea标签设置值
  2. oracle create tablespace
  3. 银行人员计算机水平,简历银行人员自我评价
  4. dell t40 固态系统盘_固态攻坚战:DELL 戴尔 INSPIRON N4050升级固态硬盘教程
  5. 流畅度优化之一——Vsync的介绍
  6. 使用adb命令行查看当前Fragment情况
  7. ionic 格式化时间
  8. 计算机应用函数count,计算机二级office考试中excel考点:countif函数的使用方法
  9. 山海演武传·黄道·第一卷 雏龙惊蛰 第十章 天下英雄在谱中(上)
  10. 自从有了暴风AI无屏电视Real6,我想撤回所有买过的电视……