跳到主要内容

Kotlin 函数

函数是组织代码的基本单元。Kotlin 的函数非常灵活,支持多种写法。

函数定义

基本语法

// 标准函数
fun greet(name: String): String {
return "Hello, $name!"
}

// 调用函数
fun main() {
val message = greet("Kotlin")
println(message) // Hello, Kotlin!
}

函数结构说明

// fun        - 关键字
// greet - 函数名
// name: String - 参数(参数名: 参数类型)
// : String - 返回值类型
// { ... } - 函数体

函数参数

默认参数

fun greet(name: String, greeting: String = "Hello"): String {
return "$greeting, $name!"
}

fun main() {
println(greet("Kotlin")) // Hello, Kotlin!
println(greet("Kotlin", "Hi")) // Hi, Kotlin!
}

命名参数

fun createUser(
name: String,
age: Int,
email: String = "[email protected]"
) {
println("Name: $name, Age: $age, Email: $email")
}

fun main() {
// 使用命名参数,顺序可以任意
createUser(age = 25, name = "Tom")
createUser("Alice", email = "[email protected]", age = 30)
}

可变参数

fun sum(vararg numbers: Int): Int {
return numbers.sum()
}

fun main() {
println(sum(1, 2, 3)) // 6
println(sum(1, 2, 3, 4, 5)) // 15

// 使用数组展开
val arr = intArrayOf(1, 2, 3)
println(sum(*arr)) // 6
}

Lambda 作为最后一个参数

// 如果 Lambda 是最后一个参数,可以放在括号外
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}

fun main() {
// 传统写法
val result1 = operate(1, 2) { a, b -> a + b }

// 如果是最后一个参数,Lambda 可以放在外面
val result2 = operate(1, 2) { a, b ->
a * b
}

println(result1) // 3
println(result2) // 2
}

单表达式函数

当函数只有一个表达式时,可以简写:

// 完整写法
fun double(x: Int): Int {
return x * 2
}

// 单表达式写法(省略大括号和 return)
fun double2(x: Int): Int = x * 2

// 类型推断
fun double3(x: Int) = x * 2

fun main() {
println(double(5)) // 10
println(double2(5)) // 10
println(double3(5)) // 10
}

返回类型

Unit 返回

// 返回 Unit(相当于 Java 的 void),可以省略
fun printHello(): Unit {
println("Hello")
}

// 省略 Unit
fun printHello2() {
println("Hello")
}

fun main() {
printHello()
}

Nothing 类型

Nothing 表示函数永远不会返回:

fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}

fun main() {
// 这个函数会抛出异常,不会正常返回
fail("Something went wrong")
}

函数作用域

顶层函数

定义在文件顶层的函数:

// File: Utils.kt
package com.example.util

fun isValidEmail(email: String): Boolean {
return email.contains("@")
}

// 调用
import com.example.util.isValidEmail

局部函数

在函数内部定义的函数:

fun outer() {
println("Outer function")

fun inner() {
println("Inner function")
}

inner() // 只能在这里调用
}

fun main() {
outer()
// inner() // 错误!无法访问局部函数
}

高阶函数

函数作为参数

// 定义接受函数的参数
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}

fun main() {
// 传入 Lambda
val result = calculate(10, 5) { a, b -> a + b }
println(result) // 15

// 传入函数引用
fun multiply(a: Int, b: Int) = a * b
val result2 = calculate(10, 5, ::multiply)
println(result2) // 50
}

函数作为返回值

fun multiplier(factor: Int): (Int) -> Int {
return { number -> number * factor }
}

fun main() {
val double = multiplier(2)
val triple = multiplier(3)

println(double(5)) // 10
println(triple(5)) // 15
}

Lambda 表达式

基本语法

// 完整语法
val sum = { a: Int, b: Int -> a + b }

// 简化:如果类型可以推断
val sum2: (Int, Int) -> Int = { a, b -> a + b }

// 调用
println(sum(1, 2)) // 3

it 简写

如果 Lambda 只有一个参数,可以使用 it

fun main() {
val list = listOf(1, 2, 3, 4, 5)

// 完整写法
list.filter { x -> x > 3 }

// it 简写
list.filter { it > 3 }

// it 用于其他场景
list.map { it * 2 } // [2, 4, 6, 8, 10]
list.forEach { println(it) }
}

Lambda 返回值

fun main() {
// Lambda 最后一行是返回值
val result = if (true) {
println("then branch")
1
} else {
println("else branch")
2
}
println(result) // 1
}

内联函数

使用 inline 关键字可以减少函数调用开销:

inline fun <T> measureTime(block: () -> T): T {
val start = System.currentTimeMillis()
val result = block()
val end = System.currentTimeMillis()
println("Time: ${end - start}ms")
return result
}

fun main() {
val result = measureTime {
Thread.sleep(100)
42
}
println("Result: $result")
}

noinline 和 crossinline

// noinline - 禁止内联特定参数
inline fun example1(inlined: () -> Unit, noinline notInlined: () -> Unit) {
inlined()
notInlined()
}

// crossinline - 允许非局部返回(但仍需内联)
inline fun example2(crossinline block: () -> Unit) {
val runnable = Runnable { block() }
}

尾递归函数

使用 tailrec 关键字优化递归:

// 普通递归 - 可能栈溢出
fun factorial(n: Int): Long {
return if (n <= 1) n else n * factorial(n - 1)
}

// 尾递归 - 由编译器优化
tailrec fun factorialTailrec(n: Int, acc: Long = 1): Long {
return if (n <= 1) acc else factorialTailrec(n - 1, n * acc)
}

fun main() {
println(factorialTailrec(10)) // 3628800
}

扩展函数

为已有类添加新函数:

// 为 String 添加扩展函数
fun String.addExclamation(): String {
return this + "!"
}

fun main() {
val str = "Hello"
println(str.addExclamation()) // Hello!
}

泛型扩展函数

// 为所有 List 添加函数
fun <T> List<T>.secondOrNull(): T? {
return if (size >= 2) this[1] else null
}

fun main() {
val list = listOf("a", "b", "c")
println(list.secondOrNull()) // b

val empty = listOf<String>()
println(empty.secondOrNull()) // null
}

小结

本章我们学习了:

  1. 函数定义:基本语法、参数类型
  2. 函数参数:默认参数、命名参数、可变参数
  3. 单表达式函数:简写语法
  4. 函数类型:Unit、Nothing
  5. 函数作用域:顶层函数、局部函数
  6. 高阶函数:函数作为参数和返回值
  7. Lambda 表达式:基本语法、it 简写
  8. 内联函数:优化高阶函数性能
  9. 尾递归:优化递归调用
  10. 扩展函数:为已有类添加功能

练习

  1. 编写一个函数,计算两个数的最大公约数
  2. 编写一个函数,接受一个 Lambda 参数,对列表进行过滤
  3. 使用扩展函数为 Int 添加阶乘计算
  4. 编写一个尾递归函数计算斐波那契数列
  5. 使用高阶函数实现一个简单的计算器