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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/11335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解zookeeper安装使用

目录 1.概述 1.1.功能 1.2.特点 1.3.数据结构 2.安装 2.1.Windows 2.2.Linux 3.基础操作 3.1.增 3.2.删 3.3.改 3.4.查 3.5.监听 4.JAVA操作Zookeeper 4.1.依赖 4.2.客户端 4.3.增 4.4.删 4.5.查 4.6.改 1.概述 1.1.功能 zookeeper&#xff0c;Apache旗下…

pdf转换word软件哪个好?式?这款软件帮你轻松实现转换

在工作中&#xff0c;我们常常遇到这样的情况&#xff1a;我们的文件可能是PDF格式的&#xff0c;但对方要求我们以Word形式发送&#xff0c;因为Word相对于PDF占用更小的内存&#xff0c;打开更方便&#xff0c;发送时间更短。这时我们需要将PDF转换为Word格式&#xff0c;然而…

【跨代码仓库合并方案】

1、背景&#xff1a; 1、wiser绑定的uiidA的定制修改内容和ELKO绑定的uiidB基本是一样的&#xff0c;需要手动粘贴同步&#xff0c;增加测试保障风险&#xff0c;还会浪费开发资源投入&#xff1b; 2、施耐德wiser和elko面板两套面板基本一致&#xff0c;但是经过new art升级后…

机器学习深度学习——感知机

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——softmax回归的简洁实现 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们…

市面上的ipad国产触控笔怎么样?精选的性价比电容笔

要知道&#xff0c;真正的苹果品牌的那款原装电容笔&#xff0c;光是一支电容笔就价格近千元。实际上&#xff0c;平替电容笔对没有太多预算的用户是个不错的选择。一支苹果品牌的电容笔&#xff0c;价格是平替品牌的四倍&#xff0c;但电容笔的书写效果&#xff0c;却丝毫不逊…

科技云报道:是时候全员FinOps了吗?

科技云报道原创。 在论坛上&#xff0c;国外某企业的真实案例引发了热议。一开始该企业只顾技术创新&#xff0c;积极上云&#xff0c;不顾成本。 直到有一天&#xff0c;高层介入喊停&#xff1a;“这个云不能再上了&#xff0c;成本已经远大于收益了”。该企业因为成本失控…

java-day01

一&#xff1a;基础常识 软件&#xff1a;按照特定顺序的计算机数据与指令的集合。可分为系统软件&#xff08;如操作系统&#xff09;和应用软件&#xff08;如QQ&#xff09; 人机交互方式&#xff1a;图形化界面&#xff08;GUI&#xff09;与命令行&#xff08;CLI&#…

性能优化 - 前端性能监控和性能指标计算方式

性能优化 - 前端性能监控和性能指标计算方式 前言一. 性能指标介绍1.1 单一指标介绍1.2 指标计算① Redirect(重定向耗时)② AppCache(应用程序缓存的DNS解析)③ DNS(DNS解析耗时)④ TCP(TCP连接耗时)⑤ TTFB(请求响应耗时)⑥ Trans(内容传输耗时)⑦ DOM(DOM解析耗时) 1.3 FP(f…

代码随想录算法训练营第二天| 977

977. 有序数组的平方y 思路&#xff0c;原数组是有序的&#xff0c;但是因为负数平方后可能变无序了&#xff0c;因此利用双指针遍历原数组&#xff0c;比较 nums[left]*nums[left]和nums[right]*nums[right]谁更大&#xff0c;然后对新数组赋值 class Solution {public int…

MFC第二十四天 使用GDI对象画笔和画刷来开发控件(分页控件选择态的算法分析、使用CToolTipCtrl开发动静态提示)

文章目录 GDI对象画笔和画刷来开发控件梯形边框的按钮控件CMainDlg.hCMainDlg.cppCLadderCtrl.hCLadderCtrl.cpp 矩形边框的三态按钮控件 CToolTipCtrl开发动静态提示CMainDlg.hCMainDlg.cppCLadderCtrl.hCLadderCtrl.cpp: 实现文件 矩形边框的三态按钮控件 CToolTipCtrl开发动…

欢乐暑假,华为儿童手表5系列为孩子位置安全保驾护航!

暑假带娃&#xff0c;就像爸妈的练兵场。幸好有 5 系列&#xff0c;离线定位、位置提醒、行为记录等安全守护功能面面俱到、样样精通&#xff0c;陪伴孩子度过悠长假期&#xff0c;也让爸妈长辈更安心更省力&#xff5e; 暑期到了&#xff0c;小朋友们都想出去玩&#xff0c;但…

修改密码和再次确认密码的js和element-ui的使用

<template><div><!-- plan的插槽 --><plan title"修改密码"><!-- 插槽的名字 --><span slot"header">修改密码</span><el-form:model"ruleForm2"status-icon:rules"rules2"ref"rul…

【数据结构】实验七:字符串

实验七 字符串实验报告 一、实验目的与要求 1&#xff09;巩固对串的理解&#xff1b; 2&#xff09;掌握串的基本操作实现&#xff1b; 3&#xff09;掌握 BF 和 KMP 算法思想。 二、实验内容 1. 给定一个字符串ababcabcdabcde和一个子串abcd,查找字串是否在主串中出现。…

【数据结构】实验一:绪论

实验一 绪论 一、实验目的与要求 1&#xff09;熟悉C/C语言&#xff08;或其他编程语言&#xff09;的集成开发环境&#xff1b; 2&#xff09;通过本实验加深对算法时间复杂度的理解&#xff1b; 3&#xff09;结合具体的问题分析算法时间复杂度。 二、实验内容 设计程…

深入学习 redis - Stream、Geospatial、HyperLogLog、Bitmap、Bitfields 类型扩展

目录 前言 Stream geospatial HyperLogLog Bitmaps Bitfields 前言 redis 中最关键的五个数据类型 String、List、Hash、Set、Zset 应用最广泛&#xff0c;同时 redis 也推出了额外的 5 个数据类型&#xff0c;他们分别是针对特殊场景才进行的应用的. Ps&#xff1a;这几种…

odoo16-domain

odoo16-domain 参考:https://blog.csdn.net/u013250491/article/details/86699928 domain的使用注意以下几点: 是在py文件中使用还是在xml中使用,py文件是在后端使用可以利用orm, 而xml是在前端渲染,使用的是js,没有办法使用orm如果在xml中使用,domain的格式建议为[[]], 二维…

Paragon NTFS2023最新版Mac读写NTFS磁盘工具

Paragon NTFS for Mac是Mac平台上一款非常优秀的读写工具&#xff0c;可以在Mac OS X中完全读写、修改、访问NTFS硬盘、U盘等外接设备的文件。这款软件最大的亮点简书可以让我们读写 NTFS 分区&#xff0c;因为在Mac OS X 系统上&#xff0c;默认状态下我们只能读取NTFS 分区&a…

速成版-带您一天学完python自动化测试(selenium)

Selenium是一套web网站的程序自动化操作解决方案。我们通过编写自动化程序&#xff0c;使得自动完成浏览器界面的相关操作&#xff0c;除了能够自动化的完成相关操作&#xff0c;还能从web页面获取相关信息&#xff0c;然后通过程序进行分析处理&#xff0c;本质上就是提升从网…

25.5 matlab里面的10中优化方法介绍——牛顿法(matlab程序)

1.简述 1 牛顿法简介 牛顿迭代法&#xff08;Newton’s method&#xff09;又称为牛顿-拉夫逊&#xff08;拉弗森&#xff09;方法&#xff08;Newton-Raphson method&#xff09;&#xff0c;它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。 多数方程不存…

【spring】spring bean的生命周期

spring bean的生命周期 文章目录 spring bean的生命周期简介一、bean的创建阶段二、bean的初始化阶段三、bean的销毁阶段四、spring bean的生命周期总述 简介 本文测试并且介绍了spring中bean的生命周期&#xff0c;如果只想知道结果可以跳到最后一部分直接查看。 一、bean的…