Kotlin标准函数 | 青训营

164 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第8天

Kotlin 的标准函数指的是Standara.kt文件中定义的函数,任何Kotlin 代码都可以自由调用所有的标准函数。它们的唯一目的是在对象的上下文中执行代码块。

作用域函数

当对一个对象调用标准函数并提供一个Lambda表达式时,它会形成一个临时作用域。在此作用域中,可以访问该对象而无需其名称。这些函数称为作用域函数。共有以下五种:let、run、with、apply 以及 also。

let

  • let函数需要传入的是调用者本身,如果不显式传入,也会默认传入,这种情况下,可以用it指代本体,并对其进行一系列操作,值得注意的是,let函数没有返回值

  • 用法:

    fun main(args: Array<String>) {
        var str: String = "hello world!"
        str.let {
            println(it.uppercase())
            println(it.subSequence(0 until it.length - 1))
        }
        println(str)
    }
    
    // 运行结果
    HELLO WORLD!
    hello world
    hello world!
    

with

  • with函数接收两个参数:

    • 参数一:需要操作的对象obj,可以为任意类型
    • 参数二:进行具体操作的Lambda表达式
  • 返回值:

    • with会返回传入的Lambda表示最后一行的结果作为返回值
  • 作用:

    • 可以简化需要对同一个对象进行的多次不同操作时的频繁调用问题
  • 用法:

    fun main(args: Array<String>) {
        var str: String = "hello world!"
        var res = with(str) {
            println(length)
            println(uppercase())
            str.subSequence(0 until length / 2)
        }
        println(res)
    }
    
    // 运行结果
    12
    HELLO WORLD!
    hello 
    
    • 注:传入with的对象,在Lambda表达式中,就自动拥有了该对象的上下文,也即该对象的所有变量和函数,所以在调用时,就不需要再指定对象了,如上例中直接用length就能取得str的长度,而不用str.length

run

  • run的作用与with的作用是一样的,只是调用方法不一样,且都会返回Lambda的最后一行代码的结果

    • run的调用方法:obj.run(lambda)
    • with的调用方法:with(obj,lambda)
  • 用法:

    fun main(args: Array<String>) {
        var str: String = "hello world!"
        var res = str.run {
            println(length)
            println(uppercase())
            str.subSequence(0 until length / 2)
        }
        println(res)
    }
    
    // 运行结果
    12
    HELLO WORLD!
    hello 
    

apply

  • apply函数的作用,与前面的runwith几乎是一样的,也是可以对传入的对象进行一系列的操作,不同的是**apply函数返回的是调用的对象本身**,而不是Lambda表达式的最后一句的结果

  • 用法:

    fun main(args: Array<String>) {
        var str: String = "hello world!"
        var res = str.apply {
            println(length)
            println(uppercase())
            str.subSequence(0 until length / 2)
        }
        println(str)
        println(res)
    }
    
    // 运行结果
    12
    HELLO WORLD!
    hello world!
    hello world!
    

also

  • also的用法与前面的let一样,都是可以省去对一个对象的重复调用,简化开发,如果没有显式指定参数,则默认也会用it表示传入的对象

  • 用法:

    fun main(args: Array<String>) {
        var str: String = "hello world!"
        var res:String = str.also {
            it.uppercase()
            it.replace('l','s')
        }
        println(str)
        println(res)
    }
    
    // 运行结果
    hello world!
    hello world!
    
    fun getRandomInt(): Int {
        return Random.nextInt(100).also {
            writeToLog("getRandomInt() generated value $it")
        }
    }
    
    val i = getRandomInt()
    

takeIf、takeUnless

  • takeIf:当提供的条件为true时,返回该对象,否则返回null

  • takeUnless:当提供的条件为false时,返回该对象,否则返回null

  • 用法:

    fun main(args: Array<String>) {
        var nums:List<Int> = listOf(1,2,3,4)
        nums.forEach {
            var res = it.takeIf { it % 2 == 0 }
            println(res)
        }
    }
    
    // 运行结果
    null
    2
    null
    4
    

小结:

标准函数区别表

函数对象引用返回值是否是扩展函数
letitLambda表达式最后一行结果
runthisLambda表达式最后一行结果
withthisLambda表达式最后一行结果不是:把上下文对象当做参数
applythis上下文对象
alsoit上下文对象

标准函数选择指南

img

参考资料