当前位置: 首页 > news >正文

Kotlin理解内置函数

目录

  • 一 内置函数
    • 1.1 apply 函数
    • 1.2 let 函数
    • 1.3 run函数
    • 1.4 with函数
    • 1.5 also函数
    • 1.6 takeIf函数
    • 1.7 takeUnless函数
    • 1.8 总结

Kotlin内置函数包括:letrunwithapplyalso,这些函数都是在Any类中定义的扩展函数,所以任何对象都可以调用这些函数。

一 内置函数

1.1 apply 函数

applyKotlin 标准库中的一个函数,它允许您在调用对象的上下文中执行一系列操作,并返回该对象本身。这在构建对象的过程中非常有用,因为它允许您在对象创建和初始化的同时进行一些链式操作。

apply 函数的签名如下:

inline fun <T> T.apply(block: T.() -> Unit): T

这里的 T 是接收者对象的类型。block 参数是一个函数字面值,它可以在接收者对象上执行一系列操作。在函数字面值内部,可以通过 this 来访问接收者对象。

下面是一个使用 apply 函数的示例,假设我们要创建一个 Person 类的对象并初始化其属性:

package Expetion/*** @description:重点理解:apply函数的返回值是调用对象本身,也就是this* @author: shu* @createDate: 2023/8/8 19:50* @version: 1.0*/
// 定义一个数据类
data class Person(var name: String = "", var age: Int = 0)
fun main(){val person = Person("张三", 20)// apply函数的返回值是调用对象本身val result = person.apply {name = "李四"age = 30}println(result)println(person)
}

在这个例子中,我们通过 apply 函数在对象初始化的过程中设置了 nameage 属性,然后将初始化后的对象赋值给 person 变量。

apply 函数的一个主要优势是它允许您在初始化对象的同时进行链式操作,而无需显式地创建中间变量。这在代码的可读性和简洁性方面非常有帮助。

1.2 let 函数

let 是·Kotlin 标准库中的另一个函数,它也用于对对象执行一系列操作,但与 apply 不同,它在操作完成后返回一个可能不同的值。let 函数的主要用途是在一个非空的对象上执行操作,同时避免空引用异常。

let 函数的签名如下:

inline fun <T, R> T.let(block: (T) -> R): R

在这里,T 是接收者对象的类型,Rblock 函数的返回类型。block 参数是一个函数字面值,它接受一个参数并返回一个值。

下面是一个使用 let 函数的示例,假设我们要对一个非空字符串执行一些操作:

package Expetion/*** @description: 重点理解:let函数的返回值是函数里面最后一行的返回值,也就是最后一行的返回值是什么,let函数的返回值就是什么* @author: shu* @createDate: 2023/8/8 19:55* @version: 1.0*/
// 定义一个数据类
data class Person01(var name: String = "", var age: Int = 0)
// let函数的返回值是函数里面最后一行的返回值
fun main(){val person = Person01("张三", 20)val result = person.let {it.name = "李四"it.age = 30"返回值"}println(result)println(person)
}

在这个例子中,我们使用了安全调用操作符 ?. 来调用 let 函数,以确保在 input 为非空的情况下才会执行 let 函数内部的操作。it 表示 input 的值,然后我们在 let 函数内部获取了字符串的长度,并将结果赋值给 result 变量。

let 函数在处理可空对象时特别有用,因为它允许您在对象非空的情况下执行一些操作,并获取一个非空的返回值。这有助于避免空引用异常并提高代码的安全性。

1.3 run函数

run 是 Kotlin 标准库中的另一个函数,它与 applylet 有一些相似之处,但在使用上略有不同。run 函数允许您在对象上执行一系列操作,并返回最后一个操作的结果。与 let 不同,run 函数不仅可以在非空对象上使用,还可以在任何对象上使用。

run 函数的签名如下:

inline fun <T, R> T.run(block: T.() -> R): R

在这里,T 是接收者对象的类型,Rblock 函数的返回类型。block 参数是一个函数字面值,它接受一个接收者对象并返回一个值。

下面是一个使用 run 函数的示例,假设我们要创建一个 Person 类的对象并执行一些操作:

package Expetion/*** @description:* @author: shu* @createDate: 2023/8/8 19:58* @version: 1.0*/
// 定义一个数据类
data class Person02(var name: String = "", var age: Int = 0)
//
fun main(){val person = Person02("张三", 20)val result = person.run {name = "李四"age = 30"返回值"}println(result)println(person)
}

在这个例子中,我们使用 run 函数在对象创建和初始化的过程中对 nameage 属性进行赋值,然后返回一个包含人物信息的字符串。

let 不同,run 函数不仅可以用于非空对象,还可以用于任何对象。它对于需要在一系列操作中执行某些操作并返回结果的情况非常有用。

使用场景区别

虽然 applyletrun 函数在某些方面相似,它们在使用场景和功能上有一些区别,让我们来总结一下这些区别:

  1. 返回值:

    • apply:始终返回接收者对象本身。
    • let:返回函数字面值的结果,通常是对接收者对象的处理结果。
    • run:返回函数字面值的结果,通常是对接收者对象的处理结果。
  2. 使用场景:

    • apply:适用于在对象初始化的过程中执行一系列链式操作,通常用于修改对象的属性。
    • let:适用于在非空对象上执行操作,可以用于执行任何类型的处理。
    • run:适用于执行一系列操作并返回最终结果,可以用于任何类型的对象。
  3. 对象引用:

    • apply:在函数字面值内部可以使用 this 引用接收者对象。
    • let:在函数字面值内部可以使用 it 引用接收者对象。
    • run:在函数字面值内部可以使用 this 引用接收者对象。
  4. 空安全:

    • apply:通常用于非空对象,但也可以用于可空对象。
    • let:主要用于非空对象上,避免空引用异常。
    • run:可以在任何对象上使用,无论是否为空。
  5. 链式操作:

    • apply:适用于在对象构建和初始化的同时进行一系列链式操作。
    • let:适用于在一系列操作中进行单独的处理。
    • run:适用于执行一系列操作并返回结果,但较适合复杂操作。

1.4 with函数

withKotlin 标准库中的另一个函数,它与之前提到的 applyletrun 有一些相似之处,但在使用方式和语义上略有不同。with 函数允许您在一个特定的对象上执行一系列操作,但不需要使用函数字面值,而是直接在一个代码块内操作对象。

with 函数的签名如下:

inline fun <T, R> with(receiver: T, block: T.() -> R): R

在这里,receiver 参数是接收者对象,T 是接收者对象的类型,Rblock 函数的返回类型。block 参数是一个函数字面值,它接受一个接收者对象并返回一个值。

下面是一个使用 with 函数的示例,假设我们有一个 Rectangle 类,我们希望计算其面积和周长:

package Expetion/*** @description:* @author: shu* @createDate: 2023/8/8 20:03* @version: 1.0*/
class Rectangle(val width: Int, val height: Int)fun main() {val rectangle = Rectangle(10, 5)val areaAndPerimeter = with(rectangle) {val area = width * heightval perimeter = 2 * (width + height)"Area: $area, Perimeter: $perimeter"}println(areaAndPerimeter)
}

在这个例子中,我们使用 with 函数在 rectangle 对象上执行一系列操作,计算了面积和周长,并将结果字符串赋值给 areaAndPerimeter 变量。

与之前提到的函数不同,with 函数更注重于在特定对象上执行一系列操作,并且不需要在函数内部使用额外的 itthis 来引用接收者对象。

1.5 also函数

also Kotlin 标准库中的另一个函数,类似于之前提到的 applyletrunwith 函数,它也用于在对象上执行一系列操作,但在使用方式和返回值方面有一些不同。also 函数允许您在一系列操作中对对象进行修改,并返回该对象本身。

also 函数的签名如下:

inline fun <T> T.also(block: (T) -> Unit): T

在这里,T 是接收者对象的类型,block 参数是一个函数字面值,它接受一个接收者对象并不返回任何值,用于执行一系列操作。

下面是一个使用 also 函数的示例,假设我们要对一个列表进行操作并输出其中的元素:

package Expetion/*** @description:* @author: shu* @createDate: 2023/8/8 20:03* @version: 1.0*/fun main() {val numbers = mutableListOf(1, 2, 3, 4, 5)numbers.also {it.add(6)it.remove(2)}.forEach {println(it)}
}

在这个例子中,我们使用 also 函数对 numbers 列表进行了添加和删除操作,然后在链式调用中调用了 forEach 函数来输出列表中的元素。

also 函数适用于那些需要在一系列操作中修改对象本身,同时返回该对象的情况。与 apply 不同,also 的主要重点是执行操作,而不是在初始化过程中进行操作。

1.6 takeIf函数

Kotlin 中,takeIf 是一个标准库函数,用于在特定条件下接收并返回对象。如果传递给 takeIf 函数的条件为真,则函数返回接收者对象,否则返回 null

takeIf 函数的签名如下:

inline fun <T> T.takeIf(predicate: (T) -> Boolean): T?

在这里,T 是接收者对象的类型,predicate 参数是一个函数字面值,它接受一个接收者对象并返回一个布尔值,用于判断是否应该接受该对象。

下面是一个使用 takeIf 函数的示例,假设我们要从一个字符串列表中找到第一个长度大于等于 5 的字符串:

package Expetion/*** @description:* @author: shu* @createDate: 2023/8/8 20:03* @version: 1.0*/fun main() {val strings = listOf("apple", "banana", "cherry", "date", "elderberry")val result = strings.firstOrNull { it.length >= 5 }?.takeIf { it.startsWith("e") }println(result)
}

在这个例子中,我们首先使用 firstOrNull 函数找到第一个满足长度大于等于 5 的字符串,然后我们通过链式调用使用 takeIf 函数来验证是否以字母 “e” 开头,如果是,则返回该字符串,否则返回 null

takeIf 函数适用于那些需要基于特定条件来选择对象的情况。

1.7 takeUnless函数

在 Kotlin 中,takeUnless 是一个标准库函数,与之前提到的 takeIf 函数类似,它也用于在特定条件下接收并返回对象。与 takeIf 不同的是,takeUnless 在条件为假时返回接收者对象,而在条件为真时返回 null

takeUnless 函数的签名如下:

inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T?

在这里,T 是接收者对象的类型,predicate 参数是一个函数字面值,它接受一个接收者对象并返回一个布尔值,用于判断是否应该拒绝该对象。

下面是一个使用 takeUnless 函数的示例,假设我们要从一个整数列表中找到第一个小于 5 的整数:

package Expetion/*** @description:* @author: shu* @createDate: 2023/8/8 20:03* @version: 1.0*/
fun main() {val numbers = listOf(3, 8, 1, 6, 4)val result = numbers.firstOrNull { it < 5 }?.takeUnless { it == 1 }println(result)
}

在这个例子中,我们使用 firstOrNull 函数找到第一个满足小于 5 的整数,然后通过链式调用使用 takeUnless 函数来验证是否等于 1,如果是,则返回 null,否则返回该整数。

takeUnless 函数适用于需要基于特定条件来排除对象的情况。与 takeIf 函数相比,takeUnless 的返回逻辑相反,因此您可以根据情况选择使用哪个函数。

1.8 总结

让我们对之前提到的几个函数进行总结,以便更清楚地了解它们之间的区别:

  1. apply

    • 返回接收者对象本身。
    • 用于在对象初始化过程中执行一系列链式操作。
    • 在函数字面值内部使用 this 引用接收者对象。
    • 适用于对象的构建和初始化,通常用于修改属性。
  2. let

    • 返回函数字面值的结果。
    • 用于在非空对象上执行操作,避免空引用异常。
    • 在函数字面值内部使用 it 引用接收者对象。
    • 适用于在一系列操作中执行单独的处理,获取处理结果。
  3. run

    • 返回函数字面值的结果。
    • 可以在任何对象上使用。
    • 在函数字面值内部使用 this 引用接收者对象。
    • 适用于执行一系列操作并返回结果,较适合复杂操作。
  4. with

    • 返回函数字面值的结果。
    • 用于在特定对象上执行一系列操作。
    • 在函数字面值内部直接操作对象,无需使用 itthis 引用。
    • 适用于在特定对象上执行多个操作,不关注初始化过程。
  5. also

    • 返回接收者对象本身。
    • 用于在一系列操作中修改对象并返回其本身。
    • 在函数字面值内部使用 it 引用接收者对象。
    • 适用于需要执行多个操作并保持链式调用,重点在于执行操作。
  6. takeIf

    • 返回接收者对象本身或 null
    • 用于根据条件接收对象,条件为真则返回 null
    • 在函数字面值内部使用 it 引用接收者对象。
    • 适用于基于条件接收对象的情况。
  7. takeUnless

    • 返回接收者对象本身或 null
    • 用于根据条件接收对象,条件为真则返回对象,否则返回 null
    • 在函数字面值内部使用 it 引用接收者对象。
    • 适用于基于条件排除对象的情况。

相关文章:

Kotlin理解内置函数

目录 一 内置函数1.1 apply 函数1.2 let 函数1.3 run函数1.4 with函数1.5 also函数1.6 takeIf函数1.7 takeUnless函数1.8 总结 Kotlin内置函数包括&#xff1a;let、run、with、apply、also&#xff0c;这些函数都是在Any类中定义的扩展函数&#xff0c;所以任何对象都可以调用…...

手机app测试

一、安装、卸载、更新、运行 1.安装、卸载 应用是否可以正常安装&#xff08;命令行安装&#xff1b;apk&#xff0f;ipa安装包安装&#xff09;&#xff08;有网&#xff0c;无网是否都正常&#xff09;卸载过程中出现死机&#xff0c;断电&#xff0c;重启等意外的情况&…...

Centos部署Git

Centos部署Git 文章目录 Centos部署Git部署步骤初始化配置免登录 部署步骤 初始化 -- 安装git yum install git配置免登录 配置git下载代码时 每次都需要输入密码的事情 -- 生成 gitconfig 文件 git config --global credential.helper store -- 配置登录邮箱 git config …...

k8s 控制器

Kubernetes&#xff08;K8S&#xff09;是一种开源的容器编排平台&#xff0c;它可以自动化地管理容器化应用程序的部署、扩展和运行。K8S中的控制器是一种重要的组件&#xff0c;它可以确保应用程序的状态与期望的状态一致。在K8S中&#xff0c;有五种常见的控制器&#xff0c…...

谷歌关闭跨域限制.(生成一个开发浏览器),Chrome关闭跨域

(一)、首先找到浏览器在电脑磁盘中的位置,并复制 (二)、复制一个浏览器的快捷方式到桌面(不影响正常浏览器) (三)、chrom鼠标右键属性&#xff0c;修改快捷方式的目标 &#xff08;四&#xff09;chrome.exe 后面添加 --disable-web-security --user-data-dir 复制的Chrome浏览…...

实践指南-前端性能提升 270% | 京东云技术团队

一、背景 当我们疲于开发一个接一个的需求时&#xff0c;很容易忘记去关注网站的性能&#xff0c;到了某一个节点&#xff0c;猛地发现&#xff0c;随着越来越多代码的堆积&#xff0c;网站变得越来越慢。 本文就是从这样的一个背景出发&#xff0c;着手优化网站的前端性能&a…...

8月11日上课内容 nginx的多实例和动静分离

多实例部署 在一台服务器上有多个tomcat的服务。 配置多实例之前&#xff0c;看单个实例是否访问正常。 1.安装好 jdk 2.安装 tomcat cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz mkdir /usr/local/tomcat mv apache-tomcat-9.0.16 /usr/local/tomcat/tomcat1 cp -a /usr…...

腾讯云CVM服务器端口在安全组中打开!

腾讯云服务器CVM端口怎么开通&#xff1f;腾讯云服务器端口是通过配置安全组规则来开通的&#xff0c;腾讯云服务器网以开通80端口为例来详细说下腾讯云轻量应用服务器开启端口的方法&#xff0c;其他的端口的开通如8080、1433、443、3306、8888等端口也适用于此方法&#xff0…...

k8s、docker添加daemon.json添加“exec-opts“: [“native.cgroupdriver=systemd“]后无法启动的问题

考虑k8s下docker下载镜像太慢&#xff0c;修改了daemon.json&#xff0c;按照手册抄&#xff0c;添加 {"exec-opts": ["native.cgroupdriversystemd"],"registry-mirrors": ["https://kn0t2bca.mirror.aliyuncs.com"] }结果发现k8s起…...

React组件性能优化实践

React组件性能优化最佳实践 React组件性能优化的核心是减少渲染真实DOM节点的频率&#xff0c;减少 Virtual DOM比对的频率。 组件卸载前进行清理操作 在组件中为 window注册的全局事件&#xff0c;以及定时器&#xff0c;在组件卸载前要清理掉&#xff0c;防止组件卸载后继…...

SpringBoot复习:(29)静态资源的配置路径

WebMvcAutoConfiguration 首页处理&#xff1a;...

mysql延时问题排查

背景介绍 最近遇到一个奇怪的问题&#xff0c;有个业务&#xff0c;每天早上七点半产生主从延时&#xff0c;延时时间12.6K&#xff1b; 期间没有抽数/备份等任务&#xff1b;查看慢日志发现&#xff0c;期间有一个delete任务&#xff0c;在主库执行了161s delete from xxxx_…...

接口设置了responseType:‘blob‘后,接收不到后端错误信息

下载文件流&#xff0c;需要接口设置responseType:blob&#xff0c;接口设置了responseType:blob后&#xff0c;拿不到后端接口的异常信息&#xff0c;我们只需要添加如下代码&#xff1a; const service axios.create({baseURL: ***, // url base url request url// withC…...

无涯教程-Perl - mkdir函数

描述 此功能使用MODE指定的模式创建一个名称和路径EXPR的目录,为清楚起见,应将其作为八进制值提供。 语法 以下是此函数的简单语法- mkdir EXPR,MODE返回值 如果失败,此函数返回0,如果成功,则返回1。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl -w$dirname &…...

css3 瀑布流布局遇见截断下一列展示后半截现象

css3 瀑布流布局遇见截断下一列展示后半截现象 注&#xff1a;css3实现瀑布流布局简直不要太香&#xff5e;&#xff5e;&#xff5e;&#xff5e;&#xff5e; 场景-在uniapp项目中 当瀑布流布局column-grap:10px 相邻两列之间的间隙为10px&#xff0c;column-count:2,2列展…...

C++初阶之一篇文章教会你list(理解和使用)

list&#xff08;理解和使用&#xff09; 什么是list特点和优势基本操作示例用法与其他序列式容器&#xff08;如 std::vector 和 std::deque&#xff09;相比&#xff0c;std::list 显著的区别和优势成员类型 list构造函数1. default (1)2. fill (2)3.range (3)4. copy (4) li…...

如何给Linux开启swap虚拟内存

查看系统内存资源 free -h 创建swap分区 dd if/dev/zero of/swapfile bs1024 count4194304dev/zero&#xff1a;是Linux的一种特殊字符设备(输入设备)&#xff0c;可以用来创建一个指定长度用于初始化的空文件&#xff0c;如临时交换文件&#xff0c;该设备无穷尽地提供0&…...

spring按条件注入@Condition及springboot对其的扩展

概述 spring的ioc极大的方便了日常开发&#xff0c;但随着业务的迭代。配置的一些参数在某些情况下需要按条件注入。 比如原先定义的db公共模块下&#xff0c;相关的配置和工具类只是基于mysql的。但是后续有模块需要使用mongo/es等其他数据库&#xff0c;又想继续使用db公共…...

MySQL多表连接查询3

目录 表结构 创建表 表数据 查询需求&#xff1a; 1.查询student表的所有记录 2.查询student表的第2条到4条记录 3.从student表查询所有学生的学号&#xff08;id&#xff09;、姓名&#xff08;name&#xff09;和院系&#xff08;department&#xff09;的信息 4.从s…...

【从零开始学习JAVA | 第四十五篇】反射

目录 前言&#xff1a; ​反射&#xff1a; 使用反射的步骤&#xff1a; 1.获取阶段&#xff1a; 2.使用阶段&#xff1a; 反射的应用场景&#xff1a; 使用反射的优缺点&#xff1a; 总结&#xff1a; 前言&#xff1a; Java中的反射是一项强大而灵活的功能&#xff0…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...