1. 变量和常量
val
:不可变变量(只读,类似 final)
var
:可变变量
类型推断:Kotlin 支持自动推断变量类型
1 2 3 4 5 6 7 8 fun main () { val name = "Alice" var age = 25 age = 26 println("Name: $name , Age: $age " ) }
2. 基本数据类型
常见类型:Int
, Double
,
String
, Boolean
, List
,
Map
等
无基本类型与引用类型的区分,全部是对象
1 2 3 4 5 6 7 8 fun main () { val integer: Int = 42 val double: Double = 3.14 val text: String = "Kotlin" val isActive: Boolean = true println("Int: $integer , Double: $double , String: $text , Boolean: $isActive " ) }
3. 控制流:if 表达式
if
在 Kotlin 中是表达式,可以返回值
替代三元运算符(Kotlin 无三元运算符)
1 2 3 4 5 6 7 8 9 10 11 fun main () { val score = 85 val grade = if (score >= 90 ) { "A" } else if (score >= 80 ) { "B" } else { "C" } println("Score: $score , Grade: $grade " ) }
4. 控制流:when 表达式
类似 switch
,但更强大,支持多种条件
也是表达式,可返回值
1 2 3 4 5 6 7 8 9 10 fun main () { val day = 3 val dayName = when (day) { 1 -> "Monday" 2 -> "Tuesday" 3 -> "Wednesday" else -> "Unknown" } println("Day $day is $dayName " ) }
5. 循环
for
:用于迭代集合或范围
while
和 do-while
:与 Java 类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun main () { println("Numbers 1 to 5:" ) for (i in 1. .5 ) { print("$i " ) } println() var count = 3 println("Counting down:" ) while (count > 0 ) { print("$count " ) count-- } }
6. 函数
使用 fun
关键字
支持默认参数、命名参数、单表达式函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 fun greet (name: String , greeting: String = "Hi" ) : String { return "$greeting , $name !" } fun sum (a: Int , b: Int ) = a + bfun apply (x: Int , op: (Int ) -> Int ) = op(x)fun double (x: Int ) : Int = x * 2 fun main () { println(greet("Alice" )) println(greet("Bob" , "Hello" )) println(sum(3 , 5 )) println(apply(5 ) { it * 2 }) println(apply(5 ) { x: Int -> x * 2 }) println(apply(5 , ::double)) }
7. 类和对象
使用 class
定义类
属性自动生成 getter/setter
支持构造函数、主构造函数、初始化块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Person (val name: String) { private val secret = 42 protected val subclassVisible = "Protected" internal val moduleVisible = "Internal" var age: Int = 0 get () = field set (value) { if (value >= 0 ) field = value } init { println("Person created: $name " ) } constructor (name: String, age: Int ) : this (name) { this .age = age } fun introduce () { println("Hi, I'm $name , $age years old." ) } fun getAgeAfterYears (years: Int ) : Int { return age + years } } fun main () { val person = Person("Alice" , 25 ) person.introduce() println("Age in 5 years: ${person.getAgeAfterYears(5 )} " ) }
8. 继承和接口
默认类是 final
,需用 open
允许继承
接口使用 interface
,实现用 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 interface Animal { fun makeSound () } open class Pet (val name: String) class Dog (name: String) : Pet(name), Animal { override fun makeSound () { println("$name says Woof!" ) } } abstract class Shape { abstract fun area () : Double } class Circle (val radius: Double ) : Shape() { override fun area () = Math.PI * radius * radius } fun main () { val dog = Dog("Buddy" ) dog.makeSound() }
9. 空安全
可空类型用 ?
表示
安全调用 ?.
,Elvis 运算符 ?:
,非空断言
!!
1 2 3 4 5 6 7 8 9 10 11 fun main () { val nullableString: String? = null println("Length: ${nullableString?.length} " ) val length = nullableString?.length ?: 0 println("Length with Elvis: $length " ) }
10. 集合
支持 List
, Set
, Map
提供不可变和可变集合:listOf
,
mutableListOf
等
1 2 3 4 5 6 7 8 9 10 fun main () { val numbers = listOf(1 , 2 , 3 , 4 ) val mutableList = mutableListOf("apple" , "banana" ) val map = mapOf(1 to "one" , 2 to "two" ) println("Numbers: $numbers " ) mutableList.add("orange" ) println("Mutable List: $mutableList " ) println("Map: $map " ) }
11. Lambda 表达式和匿名函数
Lambda 语法:{ 参数 -> 表达式 }
常用于集合操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 fun main () { val numbers = listOf(1 , 2 , 3 , 4 , 5 ) val evenNumbers = numbers.filter { it % 2 == 0 } println("Even numbers: $evenNumbers " ) val squared = numbers.map { x -> x * x } println("Squared: $squared " ) val map = mapOf("a" to 1 , "b" to 2 ) map.forEach { key, value -> println("$key =$value " ) } val names = listOf("Tom" , "Alice" , "Bob" ) names.forEach(::println) val f1 = fun (x: Int ) : Int { return x + 1 } val f2 = { x: Int -> x + 1 } val f3 = { x: Int -> println(x + 1 ) } val f4 : (Int ) -> Unit = { x -> println(x + 1 ) } }
12. 扩展函数
1 2 3 4 5 6 7 8 9 10 11 12 13 fun String.reverse () : String { return this .reversed() } fun String.addExclamation () = "$this !" fun main () { val text = "Kotlin" println(text.reverse()) println("Hello" .addExclamation()) }
13. 数据类
使用 data class
自动生成 toString
,
equals
, hashCode
等,主构造函数至少一个参数,不可被 open
1 2 3 4 5 6 7 8 data class User (val name: String, val age: Int )fun main () { val user1 = User("Alice" , 25 ) val user2 = User("Alice" , 25 ) println("User1: $user1 " ) println(user.copy(name = "Bob" )) }
14. 协程
用于异步编程,需引入 kotlinx.coroutines
使用 launch
或 async
启动协程
1 2 3 4 5 6 7 8 9 10 11 12 13 import kotlinx.coroutines.*fun main () { val suspendFunc: suspend () -> Unit = { println("Suspended" ) } runBlocking { launch { delay(1000 ) println("Hello from coroutine!" ) } println("Main thread continues" ) } }
注意 :协程示例需要添加
kotlinx-coroutines-core
依赖到项目中,否则无法运行。
概述
Kotlin 协程引入于 Kotlin
1.3,是一种基于线程的轻量级并发工具,适合处理异步任务,基于
kotlinx.coroutines
库。Kotlin
协程支持挂起(suspend)机制,可以挂起和恢复,允许以顺序风格编写异步代码,类似于同步代码,但不会阻塞线程,同时避免传统回调地狱。协程的核心优势包括资源高效(不阻塞线程)和结构化并发(确保资源管理)。每个协程必须在一个作用域(CoroutineScope
)中启动。
协程语法点包括:
启动协程(如 launch
、async
)
挂起函数
上下文和调度器(如 Dispatchers
)
取消和超时
异常处理
结构化并发(如 coroutineScope
)
通道(Channel
)
流(Flow
)
选择表达式(select
)
测试工具
协程实际应用场景包括网络请求、数据库操作、并发任务和超时处理。
语法总结
launch
启动无返回结果的协程
后台任务,如日志记录
async
启动返回结果的协程
并行计算结果
runBlocking
阻塞线程等待协程完成
测试或主函数入口
withContext
切换上下文运行挂起块
网络请求或 I/O 操作
suspend
函数
定义可挂起的异步函数
网络请求或 I/O 操作
Dispatchers
选择执行线程(如 IO、Main、Default)
UI 更新或数据库操作
Job
和 Deferred
管理任务生命周期和结果
等待任务完成或取消
取消和超时
取消协程或设置时间限制
超时网络请求
异常处理
处理协程中的异常
错误日志记录
coroutineScope
结构化并发管理子协程
确保任务顺序执行
supervisorScope
容错结构化并发
子任务失败不影响其他
Channel
协程间通信
生产者-消费者模式
Flow
处理异步数据流
实时数据更新,如传感器数据
select
选择第一个可用结果
多个异步操作竞争
yield
让出执行权
协作式多任务
joinAll
等待多个 Job 完成
批量任务同步
awaitAll
等待多个 Deferred 结果
并发结果收集
测试工具
测试协程行为
单元测试和集成测试
启动协程
14.1launch
启动不返回结果的协程。
1 2 3 4 5 6 7 8 9 import kotlinx.coroutines.*fun main () = runBlocking { launch { delay(1000L ) println("World!" ) } println("Hello," ) }
14.2async
启动返回 Deferred<T>
的协程,用于获取结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import kotlinx.coroutines.*suspend fun fetchData1 () : String = withContext(Dispatchers.IO) { delay(1000L ) "Data1" } suspend fun fetchData2 () : String = withContext(Dispatchers.IO) { delay(1000L ) "Data2" } fun main () = runBlocking { val deferred1 = async { fetchData1() } val deferred2 = async { fetchData2() } println("${deferred1.await()} and ${deferred2.await()} " ) }
14.3runBlocking
阻塞当前线程直到协程完成,常用于测试或主函数。用于在
main
函数中桥接阻塞与非阻塞代码。在作用域中启动的所有协程(如
launch {}
)必须完成,runBlocking
才会返回。
1 2 3 4 5 6 7 8 9 10 11 12 import kotlinx.coroutines.*fun main () { runBlocking { launch { delay(1000 ) println("inside launch" ) } println("Hello from runBlocking" ) } }
上面的代码中, runBlocking { ... }
会阻塞当前线程,在当前线程中创建一个顶层协程(CoroutineScope
),println("Hello from runBlocking")
是在 runBlocking
的协程中执行的(运行在主线程,但属于协程代码)。
14.4withContext
在指定上下文运行挂起块,返回结果。
1 2 3 4 5 6 7 8 9 10 11 import kotlinx.coroutines.*suspend fun fetchData () : String = withContext(Dispatchers.IO) { delay(1000L ) "Data from network" } fun main () = runBlocking { val data = fetchData() println(data ) }
挂起函数
14.5 suspend
挂起函数用 suspend
关键字标记,只能从其他挂起函数或协程中调用,支持 delay
等挂起操作。 1 2 3 4 5 6 7 8 9 10 import kotlinx.coroutines.*suspend fun doSomething () { delay(1000L ) println("Done something" ) } fun main () = runBlocking { doSomething() }
协程作用域
14.6 Kotlin 协程作用域
1
runBlocking
✅ 是
✅ 是
直到 block 执行完毕
测试、main 函数入口
✅(仅限测试/入口)
2
coroutineScope
✅ 是
❌ 否
当前 suspend
函数结束
并发封装、函数内结构化并发
✅ 推荐
3
supervisorScope
✅ 是
❌ 否
当前 suspend
函数结束
容错并发(互不影响)
✅ 推荐
4
GlobalScope
❌ 否
❌ 否
应用进程存活期间
后台任务(不推荐)
⚠️ 慎用(可能泄漏)
5
自定义 CoroutineScope(...)
✅/❌ 取决于 Job
❌ 否
由 Job 控制(手动 cancel)
封装类、组件内任务
✅ 合理使用
7
actor
/ produce
✅ 是
❌ 否
通道关闭或被取消
Channel 并发、消息队列
✅ 特定场景推荐
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 import kotlinx.coroutines.*fun main () = runBlocking { println("🔷 1. runBlocking started on [${Thread.currentThread().name} ]" ) coroutineScope { launch { delay(100 ) println("🔷 2. coroutineScope: child coroutine on [${Thread.currentThread().name} ]" ) } } try { supervisorScope { launch { delay(200 ) println("🔷 3. supervisorScope: success task" ) } launch { delay(100 ) throw RuntimeException("🔷 3. supervisorScope: failed task" ) } } } catch (e: Exception) { println("🔴 Caught exception from supervisorScope: $e " ) } val job = GlobalScope.launch { delay(300 ) println("🔷 4. GlobalScope coroutine on [${Thread.currentThread().name} ]" ) } job.join() val customScope = CoroutineScope(Job() + Dispatchers.Default) val customJob = customScope.launch { println("🔷 5. Custom CoroutineScope running on [${Thread.currentThread().name} ]" ) } val numberProducer = produce { repeat(3 ) { delay(100 ) send(it * it) } close() } for (num in numberProducer) { println("🔷 6. produce: received $num " ) } val sumActor = actor<Int > { var sum = 0 for (msg in channel) { sum += msg println("🔷 7. actor: received $msg , current sum = $sum " ) } } listOf(1 , 2 , 3 ).forEach { sumActor.send(it) } sumActor.close() println("🕒 Waiting for GlobalScope & other coroutines..." ) delay(1000 ) customJob.join() customScope.cancel() println("✅ runBlocking completed." ) }
14.7 Android 扩展作用域
1
viewModelScope
✅ 是
ViewModel 生命周期
网络/IO/业务逻辑
✅ 推荐
2
lifecycleScope
✅ 是
Activity / Fragment 生命周期
启动任务 / UI操作
✅ 推荐
3
repeatOnLifecycle
✅ 是
生命周期状态变化(如 STARTED)
生命周期感知、数据收集(Flow)
✅ 推荐
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.viewModelsimport androidx.lifecycle.Lifecycleimport androidx.lifecycle.lifecycleScopeimport androidx.lifecycle.repeatOnLifecycleimport kotlinx.coroutines.delayimport kotlinx.coroutines.flow.*import kotlinx.coroutines.launchclass MainActivity : ComponentActivity () { private val viewModel by viewModels<MyViewModel>() override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) lifecycleScope.launch { delay(300 ) println("1️⃣ lifecycleScope → Thread: ${Thread.currentThread().name} " ) } lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.timerFlow.collect { println("2️⃣ repeatOnLifecycle collect: $it " ) } } } viewModel.loadData() } }
MyViewModel.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import androidx.lifecycle.ViewModelimport androidx.lifecycle.viewModelScopeimport kotlinx.coroutines.delayimport kotlinx.coroutines.flow.*import kotlinx.coroutines.launchclass MyViewModel : ViewModel () { val timerFlow: Flow<Int > = flow { var counter = 0 while (true ) { emit(counter++) delay(1000 ) } } fun loadData () { viewModelScope.launch { delay(500 ) println("3️⃣ viewModelScope → Thread: ${Thread.currentThread().name} " ) } } }
输出
1 2 3 4 5 6 1️⃣ lifecycleScope → Thread: main 3️⃣ viewModelScope → Thread: main 2️⃣ repeatOnLifecycle collect: 0 2️⃣ repeatOnLifecycle collect: 1 2️⃣ repeatOnLifecycle collect: 2 ...
说明
lifecycleScope
→ 生命周期感知,自动取消协程(适合 UI
层数据加载等)
repeatOnLifecycle
→ 更细粒度的生命周期感知(可结合
Flow
实现 UI 活动期间自动收集)
viewModelScope
→ 随
ViewModel.onCleared()
自动取消,适合业务处理逻辑
使用场景
main 函数或测试
runBlocking
挂起函数内并发
coroutineScope
容错并发
supervisorScope
UI 层任务
viewModelScope
/ lifecycleScope
库或类封装内建 scope
CoroutineScope(...)
Flow、通道数据源
produce
/ actor
内隐含作用域
后台不销毁任务
极少情况用 GlobalScope
(通常不推荐)
14.8 协程上下文和调度器
调度器(如
Dispatchers.Main
、Dispatchers.IO
、Dispatchers.Default
、Dispatchers.Unconfined
)决定协程运行的线程。
1 2 3 4 launch(Dispatchers.Main) { } launch(Dispatchers.IO) { } launch(Dispatchers.Default) { } launch(Dispatchers.Unconfined) { }
1 2 3 4 5 6 7 import kotlinx.coroutines.*fun main () = runBlocking { launch(Dispatchers.IO) { println("Running on IO thread: ${Thread.currentThread().name} " ) } }
Job 和 Deferred
14.9 Job
🔹 Job
:表示一个可以被取消的协程任务
✅ 特点:
代表一个正在运行的协程任务
可以:
取消(job.cancel()
)
等待其完成(job.join()
)
不返回结果值 ,只表示任务的生命周期
✅ 示例:
1 2 3 4 5 6 7 8 9 10 11 12 import kotlinx.coroutines.*fun main () = runBlocking { val job = launch { delay(1000L ) println("Job completed" ) } println("Waiting for job..." ) job.join() println("Main function continues" ) }
14.10 Deferred
🔹 Deferred<T>
:表示一个带返回值的协程任务(类似于
Future<T>
)
✅ 特点:
是 Job
的子类型
表示一个异步计算的结果
使用 async
创建,调用 .await()
获取结果
也可以取消、检查是否完成
✅ 示例:
1 2 3 4 5 6 7 8 9 10 11 12 import kotlinx.coroutines.*fun main () = runBlocking { val deferred: Deferred<Int > = async { delay(1000L ) 42 } println("Doing other things..." ) val result = deferred.await() println("Result: $result " ) }
🔍 Job
与 Deferred
的对比
是否返回结果值
❌ 无
✅ 有返回值 (T
)
创建方式
launch { ... }
async { ... }
获取结果方式
无
await()
取消任务
✅ .cancel()
✅ .cancel()
等待完成
✅ .join()
✅ .await()
是否继承自 Job
✅ 本身就是
✅ 是 Job
的子接口
典型用途
启动独立任务
启动异步计算并获取值
✅ 使用建议
启动任务但不关心结果
launch
→ Job
适合 UI 更新、日志、并发 fire-and-forget
启动异步任务并获取值
async
→ Deferred<T>
比如网络请求、计算、数据处理等
💡 补充知识点:async
的懒启动模式
1 2 3 4 5 6 val deferred = async(start = CoroutineStart.LAZY) { delay(1000 ) 100 } val result = deferred.await()
取消和超时
14.11 cancel
取消:用 cancel
取消协程。
1 2 3 4 5 6 7 8 9 10 11 12 13 import kotlinx.coroutines.*fun main () = runBlocking { val job = launch { repeat(5 ) { i -> println("Coroutine executing $i " ) delay(500L ) } } delay(1300L ) job.cancel() println("Coroutine cancelled" ) }
可响应取消的方式
1 2 3 4 5 suspend fun doWork () { while (isActive) { } }
14.12 withTimeout
超时:用 withTimeout
设置时间限制。 抛出
TimeoutCancellationException
❌
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import kotlinx.coroutines.*fun main () = runBlocking { try { withTimeout(1300L ) { repeat(5 ) { i -> println("Processing $i " ) delay(500L ) } } } catch (e: TimeoutCancellationException) { println("Timed out" ) } }
14.13 withTimeoutOrNull
返回 null
,不抛异常 ✅
1 2 3 4 5 6 7 8 withTimeout(1000 ) { delay(2000 ) } val result = withTimeoutOrNull(1000 ) { delay(2000 ) "This won't return" } ?: "Timeout!"
14.14 异常处理
使用 CoroutineExceptionHandler
处理异常(launch中使用)。
1 2 3 4 5 6 7 8 9 10 11 12 import kotlinx.coroutines.*fun main () = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Caught $exception " ) } launch(handler) { throw Exception("Error in coroutine" ) } delay(1000L ) }
使用 try-catch
处理异常。
1 2 3 4 5 6 7 launch { try { throw Exception("Error" ) } catch (e: Exception) { println("Caught: $e " ) } }
协程组合与并发控制
14.15 并发执行任务 + 组合结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import kotlinx.coroutines.*suspend fun getUser () : String { delay(1000 ) println("👤 getUser completed on [${Thread.currentThread().name} ]" ) return "User123" } suspend fun getPosts () : List<String> { delay(800 ) println("📝 getPosts completed on [${Thread.currentThread().name} ]" ) return listOf("Post A" , "Post B" , "Post C" ) } fun main () = runBlocking { println("🚀 Running in [${Thread.currentThread().name} ]" ) val userDeferred = async { getUser() } val postsDeferred = async { getPosts() } val (a, b) = userDeferred.await() to postsDeferred.await() println("✅ Combined result: $a + $b " ) }
14.16 顺序执行多个挂起函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import kotlinx.coroutines.*suspend fun getUser () : String { delay(1000 ) println("👤 getUser completed on [${Thread.currentThread().name} ]" ) return "User456" } suspend fun getPosts (user: String ) : List<String> { delay(800 ) println("📝 getPosts for $user completed on [${Thread.currentThread().name} ]" ) return listOf("Post X" , "Post Y" ) } fun main () = runBlocking { println("🚀 Running in [${Thread.currentThread().name} ]" ) val user = getUser() val posts = getPosts(user) println("✅ Result for $user : $posts " ) }
区别说明
async + await
✅ 是
并发获取多个独立结果
多个不依赖关系的网络/API 请求
顺序调用
❌ 否
一个接一个
后一个依赖前一个结果
结构化并发
结构化并发的核心:
父协程自动管理子协程
作用域退出时取消未完成子协程
错误自动传播
14.17 coroutineScope
coroutineScope
: 创建作用域,等待所有子协程完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import kotlinx.coroutines.*suspend fun performTasks () = coroutineScope { launch { delay(1000L ) println("Task 1" ) } launch { delay(2000L ) println("Task 2" ) } } fun main () = runBlocking { performTasks() println("All tasks completed" ) }
14.18 supervisorScope
supervisorScope
: 类似,但子协程失败不影响其他。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import kotlinx.coroutines.*suspend fun performTasks () = supervisorScope { launch { delay(1000L ) throw Exception("Task 1 failed" ) } launch { delay(2000L ) println("Task 2 completed" ) } } fun main () = runBlocking { try { performTasks() } catch (e: Exception) { println("Caught exception: $e " ) } println("Main function continues" ) }
14.19 通道(Channels)
用于协程间通信,支持生产者-消费者模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import kotlinx.coroutines.*import kotlinx.coroutines.channels.*fun main () = runBlocking { val channel = Channel<Int >() launch { for (x in 1. .5 ) channel.send(x * x) channel.close() } launch { for (y in channel) { println(y) } } println() }
14.20 流(Flows)
Flow(协程版响应式流) 的特性:
是冷流(调用 collect 才执行)
自动挂起支持
支持背压、变换、合并等操作符(如 map、filter、combine)
处理异步数据流。
1 2 3 4 5 6 7 8 9 10 11 12 13 import kotlinx.coroutines.*import kotlinx.coroutines.flow.*fun main () = runBlocking { flow { for (i in 1. .3 ) { delay(100 ) emit(i) } }.collect { value -> println(value) } }
14.21 选择表达式(Select
Expression)
同时等待多个挂起操作,选择第一个可用结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 import kotlinx.coroutines.*import kotlinx.coroutines.selects.*suspend fun selectExample1 (scope: CoroutineScope ) : String { return try { val deferred1 = scope.async { delay(1000L ) "Result 1" } val deferred2 = scope.async { delay(500L ) "Result 2" } select<String> { deferred1.onAwait { it } deferred2.onAwait { it } } } catch (e: Exception) { "Error occurred: ${e.message} " } } suspend fun selectExample2 () : String = coroutineScope { return @coroutineScope try { val deferred1 = async { delay(1000L ) "Result 1" } val deferred2 = async { delay(500L ) "Result 2" } select<String> { deferred1.onAwait { it } deferred2.onAwait { it } } } catch (e: Exception) { "Error occurred: ${e.message} " } } fun main () { runBlocking { val result1 = selectExample1(this ) println(result1) val result2 = selectExample2() println(result2) } }
工具函数
14.23 yield
让出执行权,允许其他协程运行,适合协作式多任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import kotlinx.coroutines.*fun main () = runBlocking { launch { repeat(5 ) { println("Coroutine 1: $it " ) yield() } } launch { repeat(5 ) { println("Coroutine 2: $it " ) yield() } } }
输出:Coroutine 1
和 Coroutine 2
交替执行。
14.24 joinAll
等待多个 Job
完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import kotlinx.coroutines.*fun main () { runBlocking { val job1 = launch { delay(1000L ) println("Job 1" ) } val job2 = launch { delay(2000L ) println("Job 2" ) } joinAll(job1, job2) println("All jobs completed" ) } }
输出:Job 1
、Job 2
、All jobs completed
。
14.25 awaitAll
等待多个 Deferred
完成,返回结果列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import kotlinx.coroutines.*fun main () { runBlocking { val deferred1 = async { delay(1000L ) 1 } val deferred2 = async { delay(2000L ) 2 } val results = awaitAll(deferred1, deferred2) println(results) } }
输出:Results: [1, 2]
。
14.26 测试协程
使用 runBlockingTest
和
TestCoroutineDispatcher
测试协程,适合单元测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package testimport kotlinx.coroutines.asyncimport kotlinx.coroutines.delayimport kotlinx.coroutines.test.advanceTimeByimport kotlinx.coroutines.test.runTestimport org.junit.Assertimport kotlin.test.Testclass CoroutineTest { @Test fun testCoroutine () = runTest { val deferred = async { delay(1000L ) 42 } advanceTimeBy(1000L ) val result = deferred.await() println("Result in test: $result " ) Assert.assertEquals(42 , result) } }
1 2 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3" ) testImplementation("junit:junit:4.13.2" )
实际应用场景
14.27 网络请求(Android)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import kotlinx.coroutines.*import retrofit2.Retrofitimport retrofit2.converter.gson.GsonConverterFactoryimport retrofit2.http.GETinterface ApiService { @GET("data" ) suspend fun getData () : String } class MainViewModel : ViewModel () { private val retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/" ) .addConverterFactory(GsonConverterFactory.create()) .build() private val apiService = retrofit.create(ApiService::class .java) fun fetchData () { viewModelScope.launch { try { val data = apiService.getData() println("Fetched data: $data " ) } catch (e: Exception) { println("Error: $e " ) } } } }
14.28 数据库操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import androidx.room.*import kotlinx.coroutines.*@Entity data class User (@PrimaryKey val id: Int , val name: String)@Dao interface UserDao { @Insert suspend fun insert (user: User ) } class UserRepository (private val dao: UserDao) { suspend fun insertUser (user: User ) = withContext(Dispatchers.IO) { dao.insert(user) } } fun main () = runBlocking { val repository = UserRepository() launch { repository.insertUser(User(1 , "John" )) } }
14.29 并发 API 调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import kotlinx.coroutines.*suspend fun fetchData1 () : String = withContext(Dispatchers.IO) { delay(1000 ) "Data 1" } suspend fun fetchData2 () : String = withContext(Dispatchers.IO) { delay(1500 ) "Data 2" } fun main () = runBlocking { val deferred1 = async { fetchData1() } val deferred2 = async { fetchData2() } val results = awaitAll(deferred1, deferred2) println("Results: $results " ) }
14.30 超时处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import kotlinx.coroutines.*suspend fun longRunningTask () : String = withContext(Dispatchers.IO) { delay(3000 ) "Done" } fun main () = runBlocking { try { withTimeout(2000L ) { val result = longRunningTask() println(result) } } catch (e: TimeoutCancellationException) { println("Task timed out" ) } }
参考资料
15. 对象声明
使用 object 创建单例
1 2 3 4 5 6 7 object Singleton { fun hello () = println("Hello" ) } fun main () { Singleton.hello() }
16. 伴生对象
在类中使用 companion object 定义静态成员
1 2 3 4 5 6 7 8 9 class MyClass { companion object { fun create () = MyClass() } } fun main () { val instance = MyClass.create() }
等价于
1 2 3 4 5 public class MyClass { public static MyClass create () { return new MyClass (); } }
17. 导入
1 2 3 4 import kotlin.math.PI as MathPIfun main () { println(MathPI) }
18. 异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun validate (x: Int ) { if (x < 0 ) throw IllegalArgumentException("Negative not allowed" ) } fun main () { val result = try { validate(-1 ) "Success" } catch (e: IllegalArgumentException) { println("Error: ${e.message} " ) "Failed" } finally { println("Cleanup" ) } println("Result: $result " ) }
19. 泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Box <T >(val value: T) fun <T> printItem (item: T ) = println(item) interface Producer <out T > { fun produce () : T } class StringProducer : Producer <String > { override fun produce () = "Hello" } interface Consumer <in T > { fun consume (item: T ) } class AnyConsumer : Consumer <Any > { override fun consume (item: Any ) = println(item) } fun printList (list: List <*>) = println(list) fun main () { val intBox = Box(42 ) val strBox = Box("Kotlin" ) println("${intBox.value} , ${strBox.value} " ) printItem(42 ) printItem("Kotlin" ) val producer: Producer<String> = StringProducer() println(producer.produce()) val consumer: Consumer<Any> = AnyConsumer() consumer.consume("Hello" ) printList(listOf(1 , "A" )) }
20. 自定义注解
1 2 3 4 5 6 7 8 annotation class MyAnnotation (val priority: Int )@MyAnnotation(1) fun annotated () = println("Annotated" )fun main () { annotated() }
21. 中缀函数
1 2 3 4 5 infix fun Int .plus (x: Int ) = this + x fun main () { println(5 plus 3 ) }
22. 运算符重载
1 2 3 4 5 6 7 8 9 data class Point (val x: Int , val y: Int ) { operator fun plus (other: Point ) = Point(x + other.x, y + other.y) } fun main () { val p1 = Point(1 , 2 ) val p2 = Point(3 , 4 ) println(p1 + p2) }
23. 内联类(已废弃)
使用 inline class
定义单值包装类,编译时展开为原始类型,避免对象分配。
不支持接口实现。
使用 @JvmInline value class
替代
inline class
。
不可扩展,不可被集成。
1 2 3 4 5 6 inline class Name (val value: String)fun main () { val name = Name("Kotlin" ) println(name.value) }
内联类和内联值类特性:
❌ 继承类
不行,value class 不能继承任何类(除了 Any
)
❌ 被继承
不行,value class 自身也不能被继承
✅ 实现接口
可以实现接口
✅ 内联优化
可以提升性能,避免创建对象
24. 内联值类
场景:当需要包装单一值并保持性能(如
ID、计数、单位类型),使用内联值类;复杂对象仍使用普通
data class
。
为什么不直接使用原始类型?
内联值类为原始类型添加语义,防止误用。
代码可读性增加。
内联值类允许为原始类型添加方法或实现接口,封装特定逻辑,而不增加运行时开销。
领域驱动设计(DDD)。在复杂系统中,内联值类支持领域建模,用类型区分不同概念(如
OrderId
vs ProductId
),提高代码一致性。
内联值类可以在构造时验证值,防止非法状态,而原始类型无法限制。
内联值类通过 @JvmInline
在编译时替换为底层原始类型(如
Int
),几乎无额外内存或性能开销,接近直接使用原始类型的效率。
1 2 3 4 5 6 7 8 9 10 11 @JvmInline value class UserId (val id: Int ) : Comparable<UserId> { override fun compareTo (other: UserId ) : Int = id.compareTo(other.id) } fun main () { val userId = UserId(42 ) println(userId.id) println(userId > UserId(40 )) }
25. 无符号整数
UInt
:32 位无符号整数,ULong
:64 位,加
u
或 U
后缀。
编译为有符号整数,运行时模拟无符号行为。
1 2 3 4 5 fun main () { val uint: UInt = 42u val ulong: ULong = 123UL println("$uint , $ulong " ) }
26. SAM 转换改进
单方法接口支持 Lambda 转换
1 2 3 4 5 6 7 8 fun interface Action { fun run () } fun main () { val action = Action { println("Run" ) } action.run() }
27. 密封接口和密封类
sealed
修饰符表示
Expr
接口(或类)只能在同一模块(通常是同一文件或项目)内被实现。
外部代码无法创建新的Expr
子类,确保Expr
的所有可能实现(如Num
)是已知的。
对比普通接口,sealed
减少了运行时类型转换(如 as
Num)的需要。
意义:保证类型系统的封闭性,防止意外扩展,适合建模有限的类型集合(如表达式树)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 sealed interface Expr data class Num (val value: Int ) : Expr { operator fun plus (other: Num ) = Num(value + other.value) } data class Add (val left: Num, val right: Num) : Exprfun main () { val expr1: Expr = Num(42 ) println((expr1 as Num).value) val expr2: Expr = Add(Num(2 ), Num(3 )) println( when (expr2) { is Add -> (expr2.left + expr2.right) is Num -> expr2.value } ) }
Kotlin 的 密封类(sealed class)
是一种用于表示受限继承结构 的类,适合用来表达有限状态、事件、指令等类型的场景。sealed class
表示一个封闭的类层次结构 ,所有子类必须定义在同一个文件中。它是
抽象类 的一种变体,用于替代 enum 或 if/else
的分支判断 ,且能结合 when
表达式使用,非常强大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 sealed class Result <out T > { data class Success <out T >(val data : T) : Result<T>() data class Error (val exception: Throwable) : Result<Nothing >() object Loading : Result<Nothing >() } fun fetchData () : Result<String> { return try { val result = "Hello" Result.Success(result) } catch (e: Exception) { Result.Error(e) } } fun handle (result: Result <String >) { when (result) { is Result.Success -> println("Got data: ${result.data} " ) is Result.Error -> println("Error: ${result.exception.message} " ) Result.Loading -> println("Loading..." ) } } inline fun <T> Result<T> .onSuccess (action: (T ) -> Unit ) : Result<T> { if (this is Result.Success) action(data ) return this } inline fun <T> Result<T> .onError (action: (Throwable ) -> Unit ) : Result<T> { if (this is Result.Error) action(exception) return this } fetchData() .onSuccess { println("Success: $it " ) } .onError { println("Error: ${it.message} " ) }
👉 由于 Result
是密封类,when
表达式必须覆盖所有子类 ,否则编译报错(如果没有
else
分支)。
28. IO
1 2 3 4 5 import java.io.Filefun main () { File("test.txt" ).writeText("Hello" ) println(File("test.txt" ).readText()) }
29. 反射和运行时
需要在build.gradle.kts
文件中添加:
1 2 3 dependencies { implementation(kotlin("reflect" )) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 fun hello () = println("Hello" )data class Person (val name: String)fun main () { val ref1 = String::class println(ref1.simpleName) val ref2 = ::hello ref2() val props = Person::class .members println(props.map { it.name }) }
30. 属性委托
使用by
将属性委托给代理对象
lazy
首次访问时初始化,不可重新赋值。默认同步,需明确模式(如
LazyThreadSafetyMode.NONE
)。
Delegates.observable
:属性变化监听。
lazy
和 observable
是 Kotlin
提供的内置委托。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import kotlin.properties.Delegatesfun main () { val lazyVal: String by lazy { println("Computed" ) "Lazy" } println(lazyVal) println(lazyVal) var obsVal: String by Delegates.observable("Init" ) { property, old, new -> println("${property.name} : $old -> $new " ) } obsVal = "New" obsVal = "Final" }
31. 类委托
使用by
将接口实现委托给对象
组合优于继承,使用委托组合多个对象的行为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 interface Printer { fun printMessage (message: String ) } class ConsolePrinter : Printer { override fun printMessage (message: String ) { println("Console: $message " ) } } class DelegatingPrinter (private val printer: Printer) : Printer by printer { override fun printMessage (message: String ) { println("Delegating: $message " ) printer.printMessage(message) } } fun main () { val consolePrinter = ConsolePrinter() val delegatingPrinter = DelegatingPrinter(consolePrinter) delegatingPrinter.printMessage("Hello, Kotlin!" ) }
32. 作用域函数
Kotlin 的作用域函数(Scope
Functions) 是让你能更优雅地处理对象初始化、配置、临时作用域和链式调用的语法工具。常用的有以下
5 个:
let
null安全、链式处理
Lambda结果
it
run
初始化 + 返回值
Lambda结果
this
with
多操作 + 返回值
Lambda结果
this
apply
初始化 + 返回对象
原对象
this
also
调试副作用 + 返回对象
原对象
it
🔹 1. let
:用 it
作为对象引用
适合做null 检查 和链式操作。
1 2 3 4 val name: String? = "Kotlin" name?.let { println("名字是 $it " ) }
🔹 2. run
:用 this
引用对象,返回表达式结果
适合对象初始化 + 返回值计算
1 2 3 4 5 val length = "Kotlin" .run { println("字符串是 $this " ) length } println(length)
🔹 3. with
:不是扩展函数,作用于已有对象
适合对对象做多个操作但不返回原对象 ,而是返回表达式值。
1 2 3 4 5 6 7 val sb = StringBuilder()val result = with(sb) { append("Hello, " ) append("World!" ) toString() } println(result)
🔹 4. apply
:用 this
,返回对象自身
适合构造对象并链式设置属性
1 2 3 4 5 6 7 8 data class User (var name: String = "" , var age: Int = 0 )fun main () { val user = User().apply { name = "124" age = 25 } }
🔹 5. also
:用 it
,返回对象自身
适合用于链式调用中插入副作用逻辑 (如日志、调试)
1 2 3 4 val list = mutableListOf(1 , 2 , 3 ) .also { println("原始列表: $it " ) } .apply { add(4 ) } .also { println("添加元素后: $it " ) }
33. 内联函数
inline
函数和 lambda 代码都在编译期被“展开复制”到调用处,提高性能
noinline
在 inline 函数中 ,禁止某个 lambda 被内联
crossinline
在 inline 函数中 ,禁止 lambda 使用
return
非局部返回
inline
✅ 1. inline
:让函数和 lambda “展开”
到调用处,提高性能
1 2 3 4 5 6 7 8 9 10 11 inline fun doSomething (block: () -> Unit ) { println("Before block" ) block() println("After block" ) } fun main () { doSomething { println("Doing work" ) } }
编译后近似于 👇:
1 2 3 4 5 fun main () { println("Before block" ) println("Doing work" ) println("After block" ) }
✅ 优点:消除函数调用开销、避免创建 Function
对象(尤其在频繁调用的 lambda 中)
noinline
⚠️ 2. noinline
:阻止某个 lambda
被内联(因为你可能要传递它)
1 2 3 4 5 6 7 8 inline fun doOps ( inlineBlock: () -> Unit , noinline logging: () -> Unit ) { inlineBlock() val func = logging func() }
你必须加 noinline
,否则无法将 lambda
存成变量或传给其他函数。
crossinline
🚫 3. crossinline
:禁止 lambda 用 return
做“非局部返回”
🔸 默认情况下,内联 lambda 可以直接
return
,但有风险。
1 2 3 4 5 6 7 8 9 10 11 inline fun higherOrder (block: () -> Unit ) { println("Before" ) block() println("After" ) } fun test () { higherOrder { return } }
要禁止这种“跳出上层函数”的行为,加 crossinline
:
1 2 3 4 5 6 7 inline fun higherOrder (crossinline block: () -> Unit ) { println("Before" ) val r = Runnable { block() } r.run() }
✅ 总结对照表
inline
将函数和 lambda 在调用处展开,提升性能、支持非局部 return
noinline
禁止某个 lambda 被内联(可传递为变量)
crossinline
禁止 lambda 使用非局部
return
(可用在回调、线程等)
📌 什么时候用它们?
高频调用、性能敏感的高阶函数
inline
lambda 需要传递或存为变量
noinline
lambda 不能用 return(如线程、回调)
crossinline