第1章:函数与Lambda——Kotlin的函数式编程基石
各位同学,欢迎来到《Kotlin Android 开发(Jetpack Compose)从入门到精通》的第一章。今天咱们聊聊函数和Lambda。说实话,函数这东西,写Java的时候天天用,但Kotlin把它玩出了新花样。我个人觉得,理解好这一章,后面学Compose会轻松很多——因为Compose里到处都是Lambda。
1.1 函数定义与调用
Kotlin的函数定义,语法上比Java简洁不少。你看这个:
fun add(a: Int, b: Int): Int {
return a + b
}
调用起来也很直接:
val result = add(3, 5) // result = 8
嗯,这里有个小细节:fun关键字是必须的,参数类型写在冒号后面,返回值类型也是。跟Java比,少了public、static这些修饰符——因为Kotlin默认就是public的。
1.2 参数默认值与命名参数
这个特性我特别喜欢。写Java的时候,为了给参数提供默认值,经常要写一堆重载方法。Kotlin直接搞定:
fun createUser(name: String, age: Int = 18, city: String = "北京") {
println("姓名:$name,年龄:$age,城市:$city")
}
调用的时候,你可以只传必填参数:
createUser("张三") // 输出:姓名:张三,年龄:18,城市:北京
也可以指定某些参数:
createUser("李四", city = "上海") // 输出:姓名:李四,年龄:18,城市:上海
命名参数的好处是,你不用记住参数的顺序。我在项目中遇到过好几次,因为参数顺序搞混导致的bug——用了命名参数后,这类问题再也没出现过。
1.3 单表达式函数
刚才提到,函数体只有一行时可以简化。这就是单表达式函数:
fun double(x: Int): Int = x * 2
甚至可以省略返回值类型,让编译器自动推断:
fun double(x: Int) = x * 2
简洁吧?我写工具类函数时特别喜欢用这种写法。但要注意,如果函数逻辑复杂,还是老老实实写完整函数体比较好——可读性更重要。
1.4 高阶函数
高阶函数,说白了就是能接收函数作为参数,或者返回一个函数的函数。这是函数式编程的核心概念。
举个例子:
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
调用时,你可以传入不同的操作:
val sum = operate(3, 5) { x, y -> x + y } // 8
val product = operate(3, 5) { x, y -> x * y } // 15
你想想看,这比写一堆if-else优雅多了。我在做网络请求封装时,经常用高阶函数来处理成功和失败的回调。
1.5 Lambda表达式
Lambda就是匿名函数的一种简洁写法。基本语法是这样的:
{ 参数列表 -> 函数体 }
比如:
val sum: (Int, Int) -> Int = { x, y -> x + y }
如果Lambda只有一个参数,可以用it来隐式引用它:
val numbers = listOf(1, 2, 3, 4, 5)
val doubled = numbers.map { it * 2 } // [2, 4, 6, 8, 10]
这里有个坑,我曾经踩过:如果Lambda是函数的最后一个参数,可以把它移到括号外面。这就是所谓的「尾Lambda语法」:
// 常规写法
numbers.map({ it * 2 })
// 尾Lambda写法(更常见)
numbers.map { it * 2 }
在Compose中,这种写法随处可见。你写Button(onClick = { ... })时,其实就是在用尾Lambda。
1.6 内联函数
Lambda虽然好用,但有个性能问题:每次创建Lambda都会生成一个匿名内部类对象。如果频繁调用,会有额外的内存开销。
内联函数就是解决这个问题的。用inline关键字标记函数后,编译器会把函数体直接复制到调用处,避免创建对象:
inline fun measureTime(action: () -> Unit) {
val start = System.currentTimeMillis()
action()
val end = System.currentTimeMillis()
println("耗时:${end - start}ms")
}
调用时:
measureTime {
// 一些耗时操作
Thread.sleep(100)
}
编译后,measureTime的代码会被直接插入到调用位置,不会创建Lambda对象。性能更好。
知识体系总览
下面这张图,帮你理清本章的知识结构:
总结
这一章我们走过了Kotlin函数的核心特性。从基本的定义调用,到参数默认值、命名参数,再到单表达式函数、高阶函数、Lambda和内联函数。说白了,Kotlin在函数这块下了很大功夫,让代码写起来更舒服,跑起来更高效。
我个人建议,刚开始学的时候,先把Lambda和高阶函数用熟。这两个在Compose里天天见。内联函数可以先了解,等遇到性能瓶颈时再深入优化。
好,今天就到这里。下一章我们聊集合与泛型——又是Kotlin的一大亮点。