Kotlin中标准库函数(apply、let、run、with、also、takeIf、takeUnless)的使用详解

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家
👉点击跳转到教程

一、apply函数

apply
apply函数可以看作是一个配置函数,你可以传入一个接收者,然后调用一系列函数来配置它以便使用,如果提供lambda表达式给 apply函数执行,它会返回配置好的接收者。
可以看到,调用一个个函数类配置接收者时,变量名就省略掉了。
这是因为,在lambda表达式里,apply能让每个配置函数都作用于接收者,
这种行为有时又叫相关作用域,因为lambda表达式里的所有函数调用都是针对接收者的,或者说,它们是针对接收者的隐时调用。

fun main() {
    val file1 = File("D:\\android.txt")
    file1.setReadable(true)//可读
    file1.setWritable(true)//可写
    file1.setExecutable(false)//不能执行

    /**
     * apply
     * apply函数可以看作是一个配置函数,你可以传入一个接收者,
     * 然后调用一系列函数来配置它以便使用,如果提供lambda表达式给
     * apply函数执行,它会返回配置好的接收者。
     *
     * 可以看到,调用一个个函数类配置接收者时,变量名就省略掉了。
     * 这是因为,在lambda表达式里,apply能让每个配置函数都作用于接收者,
     * 这种行为有时又叫相关作用域,因为lambda表达式里的所有函数调用都是针对接收者的,
     * 或者说,它们是针对接收者的隐时调用。
     */
    val file2 = File("D:\\android.txt").apply {
        setReadable(true)
        setWritable(true)
        setExecutable(false)
    }
}

二、let函数

fun main() {
    /**
     * let
     * let函数能使某个变量作用于其lambda表达式里,让it关键字能引用它,let与apply
     * 比较,let会把接收者传给lambda,而apply什么都不传,匿名函数执行完,apply会返回当前接收者
     * 而let会返回lambda的最后一行。
     */
    val result = listOf(3, 2, 1).first().let {
        it * it
    }
    println(result)

    val firstElement = listOf(3, 2, 1).first()
    val result1 = firstElement * firstElement
    println(result1)

    println(formatGreeting(null))
    println(formatGreeting("android"))
}

/**
 * 使用let函数与安全调用操作符,空合并操作符一起使用
 */
fun formatGreeting(guestName: String?): String {
    return guestName?.let {
        "Welcome,$it."
    } ?: "What's your name?"
}

fun formatGreeting1(guestName: String?): String {
    return if (guestName != null) {
        "Welcome $guestName"
    } else {
        "What's your name?"
    }
}

输出结果:

9
9
What's your name?
Welcome,android.

三、run函数

fun main() {
    /**
     * run函数
     * 光看作用域行为,run和apply差不多,但与apply不同,run函数不返回接收者,run返回的是lambda表达式
     * 也就是true或者false,都是返回匿名函数的最后一行,不只是true或false
     *
     * run也能用来执行函数引用
     */
    var file = File("D:\\android.txt")
    val result = file.run {
        readText().contains("great")
    }
    println(result)

    val result1 = "The people's Republic of China.".run(::isLong)
    println(result1)

    "The people's Republic of China.".run(::isLong).run(::showMessage).run(::println)
}

fun isLong(name: String) = name.length >= 10
fun showMessage(isLong: Boolean): String {
    return if (isLong) {
        "Name is too long."
    } else {
        "Please rename"
    }
}

输出结果:

true
true
Name is too long.

四、with函数

fun main() {
    val result1 = "The people's Republic of China.".run {
        length >= 10
    }
    println(result1)
    /**
     * with函数是run的变体,它们的功能行为是一样的,但with的调用方式不一样,调用with
     * 时需要值参作为其第一个参数传入
     */
    val result2 = with("The people's Republic of China.") {
        length >= 10
    }
    println(result2)
}

输出结果:

true
true

五、also函数的使用

also函数和let函数功能相似,和let一样,also也是把接收者作为值参传给lambda
但有一点不同:also返回接收者对象,而let返回lambda结果。
因为有这个差异,also尤其适合针对同一原始对象,利用副作用做事,既然also返回的是接收者对象
你就可以基于原始接收者对象执行额外的链式调用。

fun main() {
    /**
     * also
     * also函数和let函数功能相似,和let一样,also也是把接收者作为值参传给lambda
     * 但有一点不同:also返回接收者对象,而let返回lambda结果。
     * 因为有这个差异,also尤其适合针对同一原始对象,利用副作用做事,既然also返回的是接收者对象
     * 你就可以基于原始接收者对象执行额外的链式调用。
     */
    var fileContents: List<String>
    val file = File("D://android.txt").also {
        println(it.name)
    }.also {
        fileContents = it.readLines()
    }
    println(fileContents)
}

输出结果如下:

android.txt
[great ssss]

六、takeIf函数

fun main() {
    /**
     * takeIf
     * 和其他标准函数有点不一样,takeIf函数需要判断lambda中提供的条件表达式,给出true或false结果
     * 如果判断结果为true,从takeIf函数返回接收者对象,如果是false,则返回null。
     * 如果需要判断某个条件是否满足,再决定是否可以赋值变量或执行某项任务,takeIf就非常有用,
     * 概念上讲,takeIf函数类似于if语句,但它的优势是可以直接在对象实例上调用,避免了临时变量
     * 赋值的麻烦。
     */
    val result = File("D:\\android.txt").takeIf {
        it.exists() && it.canRead()
    }?.readText()
    println(result)
    //不同takeIf函数
    val file = File("D:\\android.txt")
    val result2 = if (file.exists() && file.canRead()) {
        file.readText()
    } else {
        null
    }
    println(result2)
}

输出结果:

great ssss
great ssss

七、takeUnless函数

fun main() {
    /**
     * takeIf的辅助函数takeUnless,只有判断你给定的条件结果是false时,takeUnless才会
     * 返回原始接收者对象
     */
    val result = File("D:\\android.txt")
            .takeUnless {
                it.isHidden
            }?.readText()
    println(result)
}

输出结果:

great ssss
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Kotlin的`let`是一个作用域函数,用于在特定的上下文执行代码块。它的主要用途是进行非空判断和链式调用。 使用`let`函数,您可以在可空对象上执行操作,同时避免了显式地进行null检查。它接收一个 lambda 表达式作为参数,并将调用对象作为 lambda 表达式的参数。 下面是一个示例: ```kotlin val name: String? = "John" name?.let { println("Name is not null: $it") // 在这里可以安全地操作非空的 name 对象 // 例如:访问它的属性或调用它的方法 } ``` 在上面的代码,我们首先对可空对象`name`进行了非空判断。如果`name`不为null,`let`函数会执行 lambda 表达式的代码,其`it`表示非空的`name`对象。在 lambda 表达式,我们可以安全地访问和操作该对象。 `let`函数还可以用于链式调用。例如: ```kotlin val numbers: List<Int>? = listOf(1, 2, 3, 4, 5) numbers?.let { it.filter { number -> number % 2 == 0 } }.let { it?.forEach { evenNumber -> println("Even number: $evenNumber") } } ``` 在上面的示例,我们首先对可空列表`numbers`进行了非空判断。然后,我们使用`let`函数在 lambda 表达式对列表进行过滤操作,并将结果赋给变量`it`。接下来,我们再次使用`let`函数在 lambda 表达式对过滤后的列表进行遍历操作。 总之,`let`函数是一种简洁而安全的方式来在特定上下文执行代码块,并处理可空对象的情况。它在 Kotlin 非常常用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值