函数
本教程共 100 篇 · 第 12 篇 · 更新于 2026-07-28 · 约 7 分钟阅读
12. 函数
本节目标:学会声明函数、用默认参数和命名参数简化调用、理解顶层函数和扩展函数这些 Kotlin 特色,知道局部函数什么时候用。
函数声明
用 fun 关键字声明:
fun add(a: Int, b: Int): Int {
return a + b
}
fun是关键字。- 参数写
名: 类型。 - 返回类型写在参数列表后,用
:分隔。 - 没有返回值用
Unit(可省略,相当于 Java 的void)。
表达式函数体
函数体只有一句返回时,可以简写成表达式:
fun add(a: Int, b: Int): Int = a + b
// 返回类型也能推断
fun add(a: Int, b: Int) = a + b
无返回值
fun log(message: String): Unit { // Unit 可省略
println(message)
}
fun log(message: String) {
println(message)
}
默认参数
Kotlin 函数参数能有默认值,调用时可以省略:
fun greet(name: String, greeting: String = "Hello") {
println("$greeting, $name!")
}
greet("Android") // Hello, Android!
greet("Android", "Hi") // Hi, Android!
Tip
- 默认参数能大幅减少方法重载。Java 里要写好几个
greet重载,Kotlin 一个函数搞定。
命名参数
参数多时按位置传容易出错,可以用命名参数:
fun createUser(name: String, age: Int = 0, email: String = "", isAdmin: Boolean = false) {
// ...
}
createUser(name = "张三", isAdmin = true)
createUser("李四", email = "li@example.com")
命名参数让调用意图清晰,特别是布尔参数,isAdmin = true 比 true 好读多了。
Note
- 命名参数和默认参数配合,能写出非常灵活的 API。但调用 Java 代码时不能用命名参数(Java 不保留参数名信息,除非编译加
-parameters)。
顶层函数
Kotlin 不强制所有函数都放在类里。你可以直接在文件顶层写函数:
// Utils.kt
fun formatDate(timestamp: Long): String {
// ...
}
fun isValidEmail(email: String): Boolean {
// ...
}
调用时直接用,不用 Utils.formatDate(...)(虽然底层编译成静态方法)。Android 里工具函数都这么写,比 Java 那种塞满 Utils 类的写法干净。
// 在别的文件里
val date = formatDate(System.currentTimeMillis())
扩展函数
Kotlin 的杀手锏之一。能给已有类(包括系统类、第三方库类)加新方法,不改源码,不用继承。
语法:fun 接收者类型.函数名(...)。
// 给 String 加个扩展函数
fun String.isEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// 用起来就像原生方法
val valid = "test@example.com".isEmail()
this 指调用对象本身。扩展函数不真的修改原类,编译后是静态方法,但用起来跟成员方法一样。
Android 里常用扩展函数封装常用操作:
// 给 View 加点击防抖
fun View.onThrottleClick(interval: Long = 500, action: () -> Unit) {
setOnClickListener {
// 防抖逻辑
action()
}
}
// 给 Context 加显示 Toast
fun Context.toast(message: String) {
android.widget.Toast.makeText(this, message, android.widget.Toast.LENGTH_SHORT).show()
}
// 给 Int 加 dp 转 px
fun Int.dpToPx(context: Context): Float {
return this * context.resources.displayMetrics.density
}
Warning
- 扩展函数是静态解析的,不是多态。给父类写的扩展,子类对象调用时执行的是父类的扩展。这跟成员方法的多态不一样,注意区分。
局部函数
函数里还能定义函数,作用域限定在外层函数内:
fun processUser(user: User): String {
fun validate(field: String, value: String): Boolean {
return value.isNotBlank()
}
if (!validate("name", user.name)) return "名字为空"
if (!validate("email", user.email)) return "邮箱为空"
return "校验通过"
}
局部函数能访问外层函数的变量,适合把一个大函数里重复的小逻辑提出来,又不想污染外部作用域。
可变参数
用 vararg 表示参数个数不定:
fun sum(vararg numbers: Int): Int {
return numbers.sum()
}
sum(1, 2, 3) // 6
sum(1, 2, 3, 4, 5) // 15
传数组用展开运算符 *:
val arr = intArrayOf(1, 2, 3)
sum(*arr) // 6
infix 中缀函数
用 infix 修饰的函数,调用时可以省略点和括号:
infix fun Int.times(str: String): String {
return str.repeat(this)
}
val result = 3 times "ab" // 等同于 3.times("ab")
println(result) // ababab
Kotlin 内置的 to、until、step、in 都是中缀函数。自定义场景用在 DSL 或语义清晰时,别滥用。
Android 实战示例
// 顶层工具函数
fun formatPrice(cents: Long): String {
return "¥${"%.2f".format(cents / 100.0)}"
}
// 扩展函数:给 ViewModel 加协程启动
fun ViewModel.launch(
onError: (Throwable) -> Unit = {},
block: suspend () -> Unit
) {
viewModelScope.launch {
try { block() } catch (e: Throwable) { onError(e) }
}
}
// 带默认参数的 Compose 工具
@Composable
fun LoadingButton(
text: String,
onClick: () -> Unit,
isLoading: Boolean = false,
enabled: Boolean = true,
modifier: Modifier = Modifier
) {
// ...
}
小结
fun 声明函数,表达式体能简写。默认参数 + 命名参数减少重载。顶层函数不用塞类。扩展函数给已有类加方法,是 Kotlin 利器。局部函数提小逻辑。vararg 接可变参数。下一节学类与对象。