Kotlin 内联函数语法之let、apply、also、run、with的用法与详解
一、介绍
kotlin的语法千奇百怪,今天我们将介绍项目中频率使用比较高的几个内联函数。
二、什么叫内联函数?
内联函数 的语义很简单:把函数体复制粘贴到函数调用处 。使用起来也毫无困难,用 inline
关键字修饰函数即可。
语法:
inline fun 函数名(){ }
介绍:
在正常定义的函数最前面通过inline修饰一下,不管你在哪里调用了内联函数,该函数体内的方法都会被插入到调用出。
实战与分析:
class TestInline {inline fun log(msg: String) {System.out.println("show log=${msg}")}fun printLog() {log("I am working")}
}fun main() {val tt=TestInline()tt.log("aaaa")}
kotlin编译后的结果:
分析:
通过kotlin的源码与翻译后的对比发现,只要调用了内联函数,内联函数体的代码会被复制到调用处。
通过以上对比我们大概了解到内联函数的作用,其实对于我的分析,如果内联函数体很大,被到处引用,就会编译出特别多的多余代码,这个方式与方法的抽取调用有什么好处?目前我并没有发现这种方式的特别之处,唯一的好处就是在kotlin译码后,在结果中更方便阅读。
三、高频常用let、apply、also、run、with的介绍与使用
let、apply、also、run、with都是内联函数,但是通过使用有所不同,接下来我们做详细的分析与介绍
1、let
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return block(this)
}
从源码中可以分析,有两个泛型,一个是自身,一个是结果
所以在调用返回值传的是this,自身,返回值可以是任意类型。常见的用法就是通过对象
aa?.let这种执行。
常用的两种:
1.需要用到对象自身aa?.let{},免去对变量的判空
var aa: String? = "text-"//创建TestKKK对象,aa作为变量复制,返回ttval aaa = aa.let {val tt=TestKKK()tt.name=ittt}//返回aa的长度val length=aa?.let {it.length}
2.apply
public inline fun <T> T.apply(block: T.() -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block()return this
}
apply的用法是返回调用参数类型一样的变量。
常见的用法:
1.初始化
tt?.apply {tt = TestKKK()tt!!.name = "nodify"tt}
2.修改变量参数
tt?.apply {tt!!.name = "nodify"tt}
3.also
public inline fun <T> T.also(block: (T) -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block(this)return this
}
also的语法和apply使用类似,在block高阶函数中接受自己,但是,block不接受返回值,也就是说,你无法通过also去做初始化的工作。如果一个对戏是null,那么在使用also的使用,会报空指针
var talso: TestKKK? = nulltalso=talso?.also {talso=TestKKK()talso!!.name = "0000"talso}Log.log("also=${talso!!.name}")
所以,也就是说,变量自身的内存地址不接受also体修改,also只能修改变量的属性。
4.run
public inline fun <T, R> T.run(block: T.() -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return block()
}
run的用法比较随意。它返回任意类型,即使自身为null也可以执行返回结果。
var trun: TestKKK? = nullval run1 = trun.run {"Hello"}Log.log("run1 is String=${run1}")
val run2 = trun.run {trun = TestKKK()trun!!.name = "run"trun}Log.log("run2 is TestKKK=${run2!!.name}")
返回类型取决于block代码快最后一行的参数,如果最后一行有返回值就是该返回的类型
5.with
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return receiver.block()
}
with的用法是接受一个参数,然后返回任性参数类型。接受的参数将会是block函数体的参数。
val with = with(run3) {run2.name = run3.toString()run2}Log.log("with is TestKKK=${with.name}")
四、总结
通过以上的学习,从一开始的内联函数是什么到如何定义,以及译码后函数体的变化,都做了一次普及。最后就是我们常见的let、apply、also、run、with语法使用。
这里特别注意的是also的用法,由于also无法在block体做对象的初始化工作,所以在工作中,尽量少使用block,避免出现空指针。
如果需要初始化,可以使用apply,如果使用当前变量返回任意类型使用with、run与let。
apply:不要使用?去做空的拦截,特别在出初始化,否则初始化永远都不会执行
五、返回类型
1.返回自身的:apply与also,返回this,但是also如果是null,返回就是null,即使你在block初始化也没用
2.其他返回类型取决于block的最后一行代码,如果最后一行是变量、或者属性的get或者方法有返回值,那么久有返回值,否则为unit。
相关文章:

Kotlin 内联函数语法之let、apply、also、run、with的用法与详解
一、介绍 kotlin的语法千奇百怪,今天我们将介绍项目中频率使用比较高的几个内联函数。 二、什么叫内联函数? 内联函数 的语义很简单:把函数体复制粘贴到函数调用处 。使用起来也毫无困难,用 inline关键字修饰函数即可。 语法&a…...
Swift 中如何判断是push 过来的页面 还是present过来的 页面
在 Swift 中,可以通过检查当前视图控制器的 presentingViewController 属性来判断是通过 push 过来的页面还是 present 过来的页面。 下面是一个示例代码,展示如何判断是通过 push 还是 present 过来的页面: if let presentingViewControll…...

基于K8s环境·使用ArgoCD部署Jenkins和静态Agent节点
今天是「DevOps云学堂」与你共同进步的第 47天 第⑦期DevOps实战训练营 7月15日已开营 实践环境升级基于K8s和ArgoCD 本文节选自第⑦期DevOps训练营 , 对于训练营的同学实践此文档依赖于基础环境配置文档, 运行K8s集群并配置NFS存储。实际上只要有个K8s集…...
874. 模拟行走机器人
874. 模拟行走机器人 机器人在一个无限大小的 XY 网格平面上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令 commands : -2 :向左转 90 度-1 :向右转 90 度1 < x < 9 :…...

【Linux】- RPM 与 YUM
RPM 与 YUM 1.1 rpm 包的管理1.2 rpm 包的简单查询指令1.3 rpm 包的其它查询指令:1.4 卸载 rpm 包:2.1 安装 rpm 包3.1 yum3.2 yum 的基本指令3.3 安装指定的 yum 包3.4 yum 应用实例: 1.1 rpm 包的管理 介绍 rpm 用于互联网下载包的打包及安…...
Visual Studio 2015编译器 自动生成 XXX_EXPORTS宏
XXX_EXPORTS宏 XXX_EXPORTS宏是由Visual Studio 2015编译器自动生成的。这个宏用于标识当前项目是一个导出符号的动态链接库(DLL)项目。在使用Visual Studio 2015创建Win32项目时,编译器会自动添加这个宏到项目的预定义宏中。 这个宏的作用…...
HTML5的应用现状与发展前景
HTML5,作为Web技术的核心,已经深深地改变了我们看待和使用Web的方式。它不仅提供了数不尽的新特性和功能,还使得Web设计和开发更加互动、更加直观。这篇文章将探讨HTML5的当前应用现状,以及它的未来发展前景。 HTML5的应用现状 H…...

day44-Spring_AOP
0目录 1.2.3 1.Spring_AOP 实体类: Mapper接口: Service和实现类: 测试1: 运行后: 测试2:无此型号时 测试3:库存不足时 解决方案1:事务声明管理器 测试:…...
selenium IDE 接入jenkins-转载
Selenium-IDE脚本录制,selenium-side-runner自动化测试教程_51CTO博客_selenium ide录制脚本 备忘录...
云计算结合数据科学突破信息泛滥(下)
大家好,本文将继续讨论云计算结合数据科学突破信息泛滥的相关内容,讲述其余三个关键组成部分。 3.数据清理和预处理 收集数据并将其存储在云端之后,下一步是将数据进行转换。因为原始数据经常包含错误、不一致和缺失的值,这些都…...

蓝桥杯单片机第十二届国赛 真题+代码
iic.c /* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求,进行代码调试和修改。 */ #include <STC1…...

MyBatis学习笔记之缓存
文章目录 一级缓存一级缓存失效 二级缓存二级缓存失效二级缓存相关配置 MyBatis集成EhCache 缓存:cache 缓存的作用:通过减少IO的方式,来提高程序的执行效率 mybatis的缓存:将select语句的查询结果放到缓存(内存&…...
小程序 WxValidate.js 再次封装
util.js // 合并验证规则和提示信息 const filterRules (objectItem) > {let rules {}, messages {};for (let key in objectItem) {rules[key] objectItem[key].rulesmessages[key] objectItem[key].message}return { rules, messages } }module.exports {filterRule…...

redis 第三章
目录 1.主从复制 2.哨兵 3.集群 4.总结 1.主从复制 结果: 2.哨兵 3.集群 4.总结 通过集群,redis 解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。...
MYSQL常见面试题汇总
MYSQL常见面试题汇总 1. 什么是MYSQL?它有哪些特点? MYSQL是一种开源的关系型数据库管理系统。它具有以下特点: 高性能:MYSQL能够处理大量的并发请求,并提供快速的响应时间。可靠性:MYSQL具有数据持久化…...
Java接口通过token登录实现页面跳转到登录成功后的页面
首先,你需要在接口请求中将token作为参数传递给后端,后端需要对token进行验证并获取登录用户的信息。 在验证通过后,你可以将登录成功后的页面链接返回给前端,前端通过跳转到该链接来实现页面跳转。 以下是一个简单的Java代码演…...

Linux-文件管理
1.文件管理概述 1.Bash Shell对文件进行管理 谈到Linux文件管理,首先我们需要了解的就是,我们要对文件做些什么事情? 其实无非就是对一个文件进行、创建、复制、移动、查看、编辑、压缩、查找、删除、等等 例如 : 当我们想修改系统的主机名…...
Android getevent用法详解
TP驱动调试分享——基于Qualcomm SDM710平台Android9.0,TP 采用I2C方式和CPU进行通信_高通tp驱动_永恒小青青的博客-CSDN博客 手机触摸屏扫描信号实测波形_触摸屏报点率_AirCity123的博客-CSDN博客 如何查看TP报点率?触摸TP查看详细信息 adb shell ge…...
面试题-TS(二):如何定义 TypeScript 中的变量和函数类型?
面试题-TS(二):如何定义 TypeScript 中的变量和函数类型? 一、 变量类型的定义 在TypeScript中,我们可以使用冒号(:)来指定变量的类型。以下是一些常见的变量类型: 布尔类型(boolean):表示tr…...

【4】-多个User执行测试
目录 一个locustfile中有多个User 使用--class-picker指定执行 小结 一个locustfile中有多个User from locust import task, HttpUserclass User01(HttpUser):weight 3 # 权重host https://www.baidu.comtaskdef user_01_task(self):self.client.get(url/, nameuser_01_…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...