目录
1. 函数基础
1.1 基本语法
Kotlin
kotlin
fun add(a: Int, b: Int): Int {
return a + b
}
Java 对比
java
public int add(int a, int b) {
return a + b;
}
关键差异:
- Kotlin:
fun关键字,类型在参数名后面 - Java:类型在参数名前面
1.2 单表达式函数
Kotlin
kotlin
fun add(a: Int, b: Int): Int = a + b
// 类型推断
fun add(a: Int, b: Int) = a + b
Java 对比
java
// Java 没有单表达式函数,必须写完整
public int add(int a, int b) {
return a + b;
}
使用场景:
- 简单的计算函数
- 属性 getter
- 工具函数
1.3 Unit 类型(无返回值)
Kotlin
kotlin
fun printMessage(message: String): Unit {
println(message)
}
// Unit 可以省略
fun printMessage(message: String) {
println(message)
}
Java 对比
java
public void printMessage(String message) {
System.out.println(message);
}
关键点:
- Kotlin 的
Unit等价于 Java 的void Unit可以省略不写
2. 函数参数
2.1 默认参数
Kotlin
kotlin
fun greet(name: String, greeting: String = "Hello") {
println("$greeting, $name!")
}
// 使用
greet("Tom") // Hello, Tom!
greet("Tom", "Hi") // Hi, Tom!
Java 对比
java
// Java 不支持默认参数,需要方法重载
public void greet(String name) {
greet(name, "Hello");
}
public void greet(String name, String greeting) {
System.out.println(greeting + ", " + name + "!");
}
使用场景:
- 减少方法重载
- 提供常用默认值
- 简化 API 调用
2.2 命名参数
Kotlin
kotlin
fun createUser(
name: String,
age: Int = 0,
email: String = "",
phone: String = ""
) {
// ...
}
// 使用命名参数,可以跳过中间参数
createUser(
name = "Tom",
phone = "123456789" // 跳过 age 和 email
)
Java 对比
java
// Java 不支持命名参数,必须按顺序传参
createUser("Tom", 0, "", "123456789");
使用场景:
- 参数很多时,提高可读性
- 跳过某些默认参数
- Builder 模式的替代方案
2.3 可变参数
Kotlin
kotlin
fun sum(vararg numbers: Int): Int {
return numbers.sum()
}
// 使用
sum(1, 2, 3, 4, 5) // 15
Java 对比
java
public int sum(int... numbers) {
return Arrays.stream(numbers).sum();
}
关键差异:
- Kotlin:
vararg关键字 - Java:
...语法
使用场景:
- 工具函数:
max(),min(),sum() - 日志函数:
log("tag", "msg1", "msg2")
3. 扩展函数
3.1 什么是扩展函数?
扩展函数 允许你为已有的类添加新方法,而无需修改原类。
Kotlin
kotlin
// 为 String 添加扩展函数
fun String.removeSpaces(): String {
return this.replace(" ", "")
}
// 使用
val text = "Hello World"
val result = text.removeSpaces() // "HelloWorld"
Java 对比
java
// Java 没有扩展函数,需要工具类
public class StringUtils {
public static String removeSpaces(String str) {
return str.replace(" ", "");
}
}
String result = StringUtils.removeSpaces("Hello World");
3.2 使用场景
场景1:工具函数
kotlin
// 扩展函数
fun String.isEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// 使用
if (email.isEmail()) {
// ...
}
场景2:Android View 扩展
kotlin
// 为 View 添加扩展函数
fun View.show() {
this.visibility = View.VISIBLE
}
fun View.hide() {
this.visibility = View.GONE
}
// 使用(在传统 View 系统中)
button.show()
textView.hide()
场景3:集合操作
kotlin
// 为 List 添加扩展函数
fun <T> List<T>.secondOrNull(): T? {
return if (this.size >= 2) this[1] else null
}
// 使用
val list = listOf(1, 2, 3)
val second = list.secondOrNull() // 2
3.3 关键点
- 扩展函数是静态的:编译时确定,不是运行时多态
- 可以访问 public 成员:但不能访问 private 成员
- 优先级:类自己的方法优先于扩展函数
4. 高阶函数
4.1 什么是高阶函数?
高阶函数 是参数或返回值是函数的函数。
Kotlin
kotlin
// 函数作为参数
fun processNumbers(
numbers: List<Int>,
operation: (Int) -> Int
): List<Int> {
return numbers.map(operation)
}
// 使用
val doubled = processNumbers(listOf(1, 2, 3)) { it * 2 }
Java 对比
java
// Java 8+ 使用 Function
public List<Integer> processNumbers(
List<Integer> numbers,
Function<Integer, Integer> operation
) {
return numbers.stream()
.map(operation)
.collect(Collectors.toList());
}
4.2 使用场景
场景1:集合操作
kotlin
// map、filter、forEach 都是高阶函数
val numbers = listOf(1, 2, 3, 4, 5)
numbers.map { it * 2 } // [2, 4, 6, 8, 10]
numbers.filter { it % 2 == 0 } // [2, 4]
numbers.forEach { println(it) } // 打印每个元素
场景2:回调函数
kotlin
fun fetchData(
onSuccess: (String) -> Unit,
onError: (Exception) -> Unit
) {
try {
val data = "数据内容"
onSuccess(data)
} catch (e: Exception) {
onError(e)
}
}
// 使用
fetchData(
onSuccess = { data -> println("成功: $data") },
onError = { error -> println("错误: ${error.message}") }
)
场景3:Compose 中的使用
kotlin
@Composable
fun Button(
onClick: () -> Unit, // 高阶函数参数
content: @Composable () -> Unit
) {
// ...
}
// 使用
Button(onClick = { println("点击") }) {
Text("按钮")
}
5. 作用域函数
5.1 什么是作用域函数?
作用域函数 (let、run、with、apply、also)在对象的上下文中执行代码块。
5.2 let:安全调用 + 转换
kotlin
val name: String? = "Kotlin"
val length = name?.let {
println("名字是 $it")
it.length // 返回值
}
使用场景:
- 空安全调用
- 转换对象
- 链式调用
5.3 run:在对象上下文中执行
kotlin
val result = "Kotlin".run {
println(this) // this 是 "Kotlin"
this.length + this.uppercase().length
}
使用场景:
- 在对象上下文中执行代码
- 返回计算结果
5.4 with:非扩展函数
kotlin
val builder = StringBuilder()
val result = with(builder) {
append("Hello ")
append("World")
toString() // 返回值
}
使用场景:
- 对同一个对象做多个操作
- 不需要链式调用时
5.5 apply:配置对象
kotlin
val person = Person().apply {
name = "张三"
age = 25
email = "zhangsan@example.com"
}
使用场景:
- 对象初始化
- Builder 模式
- 配置对象属性
5.6 also:执行副作用
kotlin
val numbers = mutableListOf(1, 2, 3)
.also { println("初始: $it") }
.apply { add(4) }
.also { println("添加后: $it") }
使用场景:
- 调试日志
- 副作用操作
- 链式调用中的中间步骤
5.7 选择指南
| 函数 | 访问对象 | 返回值 | 使用场景 |
|---|---|---|---|
let |
it |
Lambda 结果 | 空安全、转换 |
run |
this |
Lambda 结果 | 对象上下文执行 |
with |
this |
Lambda 结果 | 非扩展,多操作 |
apply |
this |
对象本身 | 对象配置 |
also |
it |
对象本身 | 副作用、调试 |
6. 内联函数
6.1 什么是内联函数?
内联函数 在编译时将函数体直接插入调用处,避免函数调用的开销。
Kotlin
kotlin
inline fun <T> measureTime(block: () -> T): T {
val start = System.currentTimeMillis()
val result = block()
val end = System.currentTimeMillis()
println("耗时: ${end - start}ms")
return result
}
// 使用
val result = measureTime {
// 执行代码
}
6.2 使用场景
场景1:性能优化
kotlin
// 高阶函数默认会创建 Lambda 对象
// 使用 inline 可以避免创建对象
inline fun <T> List<T>.forEach(action: (T) -> Unit) {
for (element in this) action(element)
}
场景2:reified 类型参数
kotlin
// 只有内联函数可以使用 reified
inline fun <reified T> Gson.fromJson(json: String): T {
return fromJson(json, T::class.java)
}
// 使用
val user: User = gson.fromJson(jsonString)
6.3 关键点
- 性能优化:减少函数调用开销
- reified 支持 :内联函数可以使用
reified类型参数 - 代码膨胀:内联会增加代码体积,谨慎使用
7. 中缀函数
7.1 什么是中缀函数?
中缀函数 允许你使用中缀表示法调用函数(类似运算符)。
Kotlin
kotlin
infix fun Int.times(str: String): String {
return str.repeat(this)
}
// 使用
val result = 3 times "Hello" // "HelloHelloHello"
7.2 使用场景
场景1:DSL(领域特定语言)
kotlin
infix fun String.shouldBe(expected: String) {
if (this != expected) {
throw AssertionError("Expected $expected but got $this")
}
}
// 使用
"hello" shouldBe "hello"
场景2:集合操作
kotlin
infix fun <T> List<T>.containsAll(other: List<T>): Boolean {
return other.all { this.contains(it) }
}
// 使用
val list1 = listOf(1, 2, 3)
val list2 = listOf(1, 2)
val result = list1 containsAll list2 // true
7.3 关键点
- 可读性:让代码更接近自然语言
- DSL 构建:常用于构建 DSL
- 限制:必须是成员函数或扩展函数,只能有一个参数
8. 运算符重载
8.1 什么是运算符重载?
运算符重载允许你为类定义运算符的行为。
Kotlin
kotlin
data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}
}
// 使用
val p1 = Point(1, 2)
val p2 = Point(3, 4)
val p3 = p1 + p2 // Point(4, 6)
Java 对比
java
// Java 不支持运算符重载
Point p3 = p1.add(p2);
8.2 常用运算符
| 运算符 | 函数名 | 示例 |
|---|---|---|
+ |
plus |
a + b |
- |
minus |
a - b |
* |
times |
a * b |
/ |
div |
a / b |
== |
equals |
a == b |
[] |
get |
a[i] |
in |
contains |
a in b |
8.3 使用场景
场景1:数学运算
kotlin
data class Money(val amount: Double) {
operator fun plus(other: Money): Money {
return Money(amount + other.amount)
}
}
val total = Money(10.0) + Money(20.0) // Money(30.0)
场景2:集合操作
kotlin
operator fun <T> List<T>.get(index: Int): T {
return this[index]
}
val list = listOf(1, 2, 3)
val item = list[0] // 1
9. 函数类型和 Lambda
9.1 函数类型
Kotlin
kotlin
// 函数类型
val add: (Int, Int) -> Int = { a, b -> a + b }
// 使用
val result = add(1, 2) // 3
Java 对比
java
// Java 使用 Function 接口
Function<Integer, Function<Integer, Integer>> add =
a -> b -> a + b;
9.2 Lambda 表达式
Kotlin
kotlin
// Lambda 语法
val numbers = listOf(1, 2, 3, 4, 5)
numbers.filter { it > 3 } // [4, 5]
numbers.map { it * 2 } // [2, 4, 6, 8, 10]
numbers.forEach { println(it) } // 打印每个元素
Java 对比
java
numbers.stream()
.filter(x -> x > 3)
.map(x -> x * 2)
.forEach(System.out::println);
9.3 使用场景
- 集合操作 :
map、filter、forEach - 回调函数:事件处理、异步回调
- Compose :
onClick、onValueChange等
10. 实际应用场景
10.1 场景1:工具函数库
kotlin
// 扩展函数
fun String.isEmail(): Boolean {
return this.matches(Regex("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"))
}
fun View.show() {
this.visibility = View.VISIBLE
}
fun View.hide() {
this.visibility = View.GONE
}
// 使用
if (email.isEmail()) {
// ...
}
button.show()
10.2 场景2:Compose 中的高阶函数
kotlin
@Composable
fun MyScreen() {
var count by remember { mutableStateOf(0) }
// onClick 是高阶函数参数
Button(onClick = { count++ }) {
Text("计数: $count")
}
// LaunchedEffect 是高阶函数
LaunchedEffect(count) {
println("Count changed: $count")
}
}
10.3 场景3:Repository 模式
kotlin
interface UserRepository {
suspend fun getUser(id: Int): Result<User>
}
class UserRepositoryImpl : UserRepository {
override suspend fun getUser(id: Int): Result<User> {
return try {
val user = apiService.getUser(id)
Result.success(user)
} catch (e: Exception) {
Result.failure(e)
}
}
}
10.4 场景4:作用域函数优化代码
kotlin
// 使用 apply 初始化对象
val paint = Paint().apply {
isAntiAlias = true
color = Color.RED
strokeWidth = 4f
}
// 使用 let 安全调用
val length = nullableString?.let {
println("处理: $it")
it.length
}
// 使用 also 调试
val result = calculate()
.also { println("计算结果: $it") }
.also { logToFile(it) }
总结
函数特性速查表
| 特性 | 说明 | 使用场景 |
|---|---|---|
| 默认参数 | 参数有默认值 | 减少重载、简化 API |
| 命名参数 | 按名称传参 | 参数多时提高可读性 |
| 扩展函数 | 为类添加方法 | 工具函数、DSL |
| 高阶函数 | 参数/返回值是函数 | 回调、集合操作 |
| 作用域函数 | 在对象上下文中执行 | 链式调用、对象配置 |
| 内联函数 | 编译时内联 | 性能优化、reified |
| 中缀函数 | 中缀表示法 | DSL 构建 |
| 运算符重载 | 定义运算符行为 | 数学运算、集合操作 |
核心原则
- 优先使用扩展函数:为已有类添加功能
- 合理使用默认参数:减少方法重载
- 高阶函数简化代码:回调、集合操作
- 作用域函数提高可读性:链式调用、对象配置
- 谨慎使用内联函数:只在性能关键处使用
记忆口诀
- 扩展函数 = "为类添加方法,无需修改原类"
- 高阶函数 = "参数或返回值是函数"
- 作用域函数 = "在对象上下文中执行代码"
- 内联函数 = "编译时插入,避免调用开销"
- 中缀函数 = "中缀表示法,类似运算符"
掌握这些,你就能写出更优雅、更简洁的 Kotlin 代码!