Skip to content

函数声明与默认参数

源:Kotlin 函数参考手册

Kotlin 函数 (Fun) 是"一等公民"。通过简化语法、默认参数和中缀调用,它极大地增强了代码的表达力与灵活性。

基础语法

Kotlin 支持两种函数体形式:代码块体表达式体

kotlin
fun add(a: Int, b: Int): Int {
    return a + b
}
kotlin
// 自动推导返回类型,代码更紧凑
fun multiply(a: Int, b: Int) = a * b

返回值 Unit

如果函数不返回任何有意义的值,其返回类型为 Unit (对应 Java 的 void)。Unit 类型声明通常省略。

kotlin
fun log(message: String) { // : Unit 已省略
    println(message)
}

作用域与可见性

Kotlin 函数可以定义在文件顶层,无需像 Java 那样必须包裹在类中。

可见性修饰符说明
public(默认) 随处可见
internal同一模块 (Module) 内可见
protected子类可见 (仅限类成员)
private文件内或类内可见

局部函数 (Local Functions)

你可以在函数内部定义函数,支持闭包 (访问外部变量)。

kotlin
fun saveUser(user: User) {
    // 局部函数:封装重复校验逻辑
    fun validate(value: String, field: String) {
        if (value.isEmpty()) throw IllegalArgumentException("$field is empty")
    }
    
    validate(user.name, "Name")
    validate(user.email, "Email")
    // ...
}

默认参数与具名参数 (Named Arguments)

这是 Kotlin 减少重载 (Overload) 数量的神器。

kotlin
fun reformat(
    str: String,
    normalizeCase: Boolean = true,
    upperCaseFirstLetter: Boolean = true,
    divideByCamelHumps: Boolean = false,
    wordSeparator: Char = ' '
) { /*...*/ }

// 调用时可以只传部分参数,且不依赖顺序
reformat("String!", wordSeparator = '_')

Java 互操作:@JvmOverloads

Java 不支持默认参数。为了在 Java 中也能方便调用,需要添加 @JvmOverloads 注解,编译器会生成多个重载方法。 这对自定义 Android View (构造函数重载) 尤其重要。

kotlin
class CustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr)

中缀函数 (Infix Functions)

中缀函数允许省略点号和括号,让代码像自然语言一样流畅。典型场景是 mapto

kotlin
// 定义扩展函数为 infix
infix fun Int.vs(other: Int): String {
    return if (this > other) "Win" else "Lose"
}

// 调用
val gameResult = 5 vs 3 // 输出 "Win"

// 标准库示例:构建 Pair
val map = mapOf(
    "Key" to "Value", // "Key".to("Value")
    "User" to "Admin"
)

变长参数 (Varargs)

使用 vararg 关键字接收不定数量的参数。

kotlin
fun <T> asList(vararg ts: T): List<T> {
    val result = ArrayList<T>()
    for (t in ts) result.add(t)
    return result
}

val list = asList(1, 2, 3)

// 伸展操作符 (Spread Operator): *
// 将已有的数组展开传入
val array = arrayOf(7, 8, 9)
val combined = asList(1, 2, *array)

尾递归优化 (Tail Recursion)

对于算法中的递归调用,使用 tailrec 修饰符可以让编译器将其优化为高效的循环 (Loop),避免 StackOverflowError

kotlin
tailrec fun gcd(a: Int, b: Int): Int {
    // 递归调用必须是函数的最后一个操作
    return if (b == 0) a else gcd(b, a % b)
}