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
}
小结
本章我们学习了:
- 函数定义:基本语法、参数类型
- 函数参数:默认参数、命名参数、可变参数
- 单表达式函数:简写语法
- 函数类型:Unit、Nothing
- 函数作用域:顶层函数、局部函数
- 高阶函数:函数作为参数和返回值
- Lambda 表达式:基本语法、it 简写
- 内联函数:优化高阶函数性能
- 尾递归:优化递归调用
- 扩展函数:为已有类添加功能
练习
- 编写一个函数,计算两个数的最大公约数
- 编写一个函数,接受一个 Lambda 参数,对列表进行过滤
- 使用扩展函数为 Int 添加阶乘计算
- 编写一个尾递归函数计算斐波那契数列
- 使用高阶函数实现一个简单的计算器