Kotlin 函数与 Lambda 表达式

Kotlin 函数与Lambda表达式

一、Kotlin 函数

1. kotlin 定义函数


/**
 * 定义函数。无参,无返回值。
 * 也可以使用 Unit 表明没有返回值,同 Java 的 void
 */
fun function1() {
    println("no params func")
}

/**
 * 定义函数,返回2个参数拼接的结果字符串
 *
 * @param param1 int
 * @param param2 String
 * @return String
 */
fun function2(param1: Int, param2: String): String {
    val result = param1.toString() + param2
    println(result)
    return result
}

/**
 * 定义函数,返回结果为可空字符串
 *
 * @param param Int
 * @return String? nullable
 */
fun function3(param: Int): String? {
    if (param < 0) {
        return null
    }
    println(param)
    return param.toString()
}

/**
 * 单表达式函数,返回2个参数的和
 *
 * @param param1 int
 * @param param2 int
 * @return int param1 + param2
 */
fun function4(param1: Int, param2: Int) = param1 + param2

// 打印 参数 列表
fun function5(param1: Int, param2: Int) {
    println("param1: $param1, param2: $param2")
}

/**
 * 定义函数,指定参数默认值
 *
 * @param param1 int
 * @param param2 int
 */
fun function6(param1: Int = -1, param2: Int = -2) {
    println("param1: $param1, param2: $param2")
}

/**
 * 定义函数,参数数量可变。
 * 同 Swift func(param: Int...) { }
 *
 * @param param1 int
 * @param param2 String 数量可以是多个
 */
fun function7(param1: Int, vararg param2: String) {
    println("param1: $param1")
    param2.forEach {
        println("param2 item: $it")
    }
}


2. kotlin 调用函数


fun main() {
    // 1. 调用函数
    function1() // no params func
    function2(1, "2") // 12
    function3(3) // 3
    function4(1, 2) // 3

    // 2. 调用函数时指定参数的值
    function5(1, 2) // param1: 1, param2: 2 下同
    function5(param1 = 1, 2)
    function5(1, param2 = 2)
    function5(param1 = 1, param2 = 2)
    function5(param2 = 2, param1 = 1)
	
	// 3. 调用函数时使用参数默认值,对减少函数重载非常有用
    // 建议将有默认值的参数放在形参列表的最后
    function6() // param1: -1, param2: -2
    function6(3) // param1: 3, param2: -2
    function6(3, 4) // param1: 3, param2: 4
    function6(param2 = 4) // param1: -1, param2: 4

    // 4. 数量可变参数
    function7(0, "str1", "str2", "str3")
    
    // 使用 * 将数组传入可变参数
    val arr = arrayOf("str1", "str2", "str3")
    function7(0, *arr)
}


3. kotlin 局部函数


/**
 * 定义函数,内嵌3个局部函数
 */
fun function8(type: String, param1: Int, param2: Int): Int {
    println("param1: $param1, param2: $param2")

    fun funcInner1(p0: Int, p1: Int): Int {
        return max(p0, p1)
    }

    fun funcInner2(p0: Int, p1: Int): Int {
        return min(p0, p1)
    }

    fun funcInner3(p0: Int, p1: Int): Int {
        return p0 * p1
    }

    val result = when (type) {
        "max" -> funcInner1(param1, param2)
        "min" -> funcInner2(param1, param2)
        else -> funcInner3(param1, param2)
    }
    println("function8: $result")
    return result
}

fun main() {
 	// 局部函数调用
    function8("max", 1, 2) // 2
    function8("min", 1, 2) // 1
    function8("multiply", 2, 3) // 6
}


4. kotlin 高阶函数,函数引用


fun main() {
    // 使用函数的引用来调用函数,kotlin 使用 :: 引用函数
    val funcRefer = ::function3
    // 使用函数引用加括号来调用函数
    funcRefer(1) // 1

    // func1 的函数类型为 (Int, String) -> String
    fun func1(p0: Int, p1: String): String {
        return p1
    }

    // func2 的函数类型为 (Int) -> Int
    fun func2(p0: Int): Int {
        println("func2 param: $p0")
        return p0
    }

    // func3 的函数类型为 () -> Unit
    fun func3() {
    }

    // 将函数类型作为参数使用
    fun func4(param: Int, fn: (Int) -> Int) {
        fn(param)
    }
    func4(100, ::func2) // func2 param: 100

    // 将函数类型作为返回值使用。这里只做模拟,直接返回函数 func2 的引用
    fun func5(): (Int) -> Int {
        return ::func2
    }
    
    // 获取返回的函数
    val funcResult = func5()
    funcResult(200) // func2 param: 200
    funcResult.invoke(200) // 同上 func2 param: 200
    func5()(200) // 同上 func2 param: 200
    
	// 匿名函数。即没有指定函数名称
    val anonymousFunc = fun(p0: Int, p1: Int): Int {
        return p0 + p1
    }
    println(anonymousFunc(1, 2)) // 3
}


二、Kotlin lambda 表达式

lambda 表达式 相当于简化的匿名函数

1. kotlin 定义 lambda 表达式


fun main() {
	// 1. kotlin 定义 lambda 表达式,参数为 Int,返回值为 String 类型
	val lambda: (Int) -> String = { it ->
        // it 默认指代参数
        it.toString()
    }
    println("lambda result: ${lambda(300)}") // lambda result: 300

    // 2. 也可以自行指定参数名为 param
    val lambda2: (Int) -> String = { param ->
        param.toString()
    }

    // 3. 当不使用入参时,也可以指定参数名为 _
    val lambda3: (Int) -> String = { _ ->
        "nothing"
    }
}

// 定义函数,返回表达式类型为 (Int, Int) -> Int
fun getFunc(type: String): (Int, Int) -> Int {
    return when (type) {
        "max" -> { p0: Int, p1: Int ->
            max(p0, p1)
        }
        "min" -> { p0: Int, p1: Int ->
            min(p0, p1)
        }
        else -> { p0: Int, p1: Int ->
            p0 * p1
        }
    }
}


2. kotlin 调用 lambda 表达式


fun main() {
    // 获取求最小值函数
    val funcLambda = getFunc("min")
    println(funcLambda(2, 3)) // 2
}


三、Kotlin 内联函数

  1. 当形参中含有 函数类型 或 lambda 表达式时,为了减少函数执行过程中压栈和出栈产生的时间和空间开销
    可以使用内联 inline 简化函数,相当于将 fn 函数的执行体复制到调用处执行,适合执行体代码简单的函数。
  2. 注意:
  • 当 fn 中含有大量代码时,不适合使用内联,因为当函数被大量调用时, 复制 fn 的代码会造成更大的性能开销
  • 如果不希望部分参数被内联,可以使用 noinline 修饰参数

1. kotlin 使用 inline 定义内联函数


/**
 * kotlin 定义内联函数 inline
 *
 * @param list
 * @param fn 将被内联化
 *
 * @return list
 */
inline fun compute(list: List<Int>, fn: (Int) -> Int): ArrayList<Int> {
    val newList = arrayListOf<Int>()
    list.forEach {
        val newValue = fn(it) // val newValue = it * it , 直接将表达式复制到了这里
        newList.add(newValue)
    }
    return newList
}


2. kotlin 使用 noinline 阻止内联


/**
 * kotlin 选择性内联 noinline
 * 定义内联函数,使用 noinline 修饰参数,阻止 fn2 被内联
 * @param fn1 将被内联
 * @param fn2 不会被内联
 */
inline fun func(fn1: (Int) -> Int, noinline fn2: (Int) -> Int) {
    println(fn1(1))
    println(fn2(1))
}


3. kotlin 使用 crossinline 修饰参数


/**
 * 当 函数 或 lambda表达式 是在其他的上下文中被调用时,使用 crossinline
 * 如果不加,会提示:不能在这里内联'fn':它可能包含非本地返回。
 * 意思是 fn 中含有 return 代码,会直接结束函数。
 *
 * @param fn 不是直接在函数的上下文中调用,而是在 Runnable 中
 */
inline fun funcCross(crossinline fn: (Int) -> Int) {
    val thread = Thread(Runnable {
        println(fn(3))
    })
    thread.start()
}


4. kotlin 调用内联函数


fun main() {
	// 当最后一个参数为 lambda 时,可以将表达式写在括号外面。同 Swift 的后置闭包
    val list = compute(arrayListOf(1, 2, 3)) { it * it }
    println(list) // [1, 4, 9]

    funcCross { it * it } // 9
}


附 Github 源码:TestFunction

你可能感兴趣的:(Kotlin,kotlin,android,开发语言)