Kotlin 习题集 · 高级篇
涵盖 DSL、反射、协程深层、委托、设计模式、性能优化等高级内容。
第一章 DSL 构建
1.1 类型安全构建器
题目: 使用类型安全构建器模式构建 HTML DSL,实现以下调用方式:
kotlin
html {
head {
title { +"My Page" }
}
body {
h1 { +"Welcome" }
p { +"Hello, Kotlin!" }
}
}
答案:
kotlin
// 定义可嵌套的元素接口
open class Tag(val name: String) {
val children = mutableListOf<Tag>()
protected fun <T : Tag> initTag(tag: T, init: T.() -> Unit): T {
tag.init()
children.add(tag)
return tag
}
override fun toString() = "<$name>${children.joinToString("")}</$name>"
}
class HTML : Tag("html") {
fun head(init: Head.() -> Unit) = initTag(Head(), init)
fun body(init: Body.() -> Unit) = initTag(Body(), init)
}
class Head : Tag("head") {
fun title(init: Title.() -> Unit) = initTag(Title(), init)
}
class Title : Tag("title") {
operator fun String.unaryPlus() {
children.add(TextNode(this))
}
}
class Body : Tag("body") {
fun h1(init: H1.() -> Unit) = initTag(H1(), init)
fun p(init: P.() -> Unit) = initTag(P(), init)
}
class H1 : Tag("h1")
class P : Tag("p")
class TextNode(val text: String) : Tag("") {
override fun toString() = text
}
// 顶层 DSL 入口
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
fun main() {
val doc = html {
head {
title { +"My Page" }
}
body {
h1 { +"Welcome" }
p { +"Hello, Kotlin!" }
}
}
println(doc)
// <html><head><title>My Page</title></head><body><h1>Welcome</h1><p>Hello, Kotlin!</p></body></html>
}
1.2 接收者类型与 it
题目: 实现一个 SQL 构建 DSL:
kotlin
val query = select {
from("users")
where("age > 18")
orderBy("name")
}
答案:
kotlin
class QueryBuilder {
private var table: String = ""
private var whereClause: String? = null
private var orderByClause: String? = null
fun from(table: String) {
this.table = table
}
fun where(condition: String) {
this.whereClause = condition
}
fun orderBy(column: String) {
this.orderByClause = column
}
fun build(): String {
return buildString {
append("SELECT * FROM $table")
whereClause?.let { append(" WHERE $it") }
orderByClause?.let { append(" ORDER BY $it") }
}
}
}
fun select(init: QueryBuilder.() -> Unit): QueryBuilder {
val builder = QueryBuilder()
builder.init()
return builder
}
fun main() {
val query = select {
from("users")
where("age > 18")
orderBy("name")
}
println(query.build())
// SELECT * FROM users WHERE age > 18 ORDER BY name
}
第二章 反射
2.1 基本反射操作
题目: 使用反射实现通用对象复制函数 deepCopy,能够复制任意对象的所有属性。
答案:
kotlin
import kotlin.reflect.full.*
import kotlin.reflect.*
data class Person(val name: String, val age: Int)
class Address(val city: String, val zip: String)
data class Employee(
val name: String,
val age: Int,
val address: Address
)
fun <T : Any> deepCopy(obj: T): T {
val constructor = obj::class.primaryConstructor!!
val params = constructor.parameters
val args = params.map { param ->
val value = obj::class.memberProperties
.firstOrNull { it.name == param.name }
?.get(obj)
when {
param.type.isDataClass -> value?.let { deepCopy(it as Any) }
param.type.isCollection -> (value as? List<*>)?.map { it?.let { deepCopy(it as Any) } }
else -> value
}
}.toTypedArray()
return constructor.call(*args)
}
fun main() {
val addr = Address("Beijing", "100000")
val emp1 = Employee("Alice", 30, addr)
val emp2 = deepCopy(emp1)
println(emp2) // Employee(name=Alice, age=30, address=Address(city=Beijing, zip=100000))
// 验证是深拷贝
println(emp1.address === emp2.address) // false (不同引用)
}
2.2 反射与注解
题目: 定义 @Config 注解,使用反射自动从配置文件读取值并注入到对象的属性。
答案:
kotlin
import kotlin.reflect.*
@Target(AnnotationTarget.PROPERTY)
annotation class Config(val key: String)
class AppConfig {
@Config("app.name")
var appName: String = ""
@Config("app.version")
var version: String = ""
@Config("app.debug")
var debug: Boolean = false
}
fun loadConfig(config: AppConfig, configMap: Map<String, String>) {
config::class.memberProperties.forEach { property ->
val annotation = property.findAnnotation<Config>()
if (annotation != null) {
val value = configMap[annotation.key]
if (value != null) {
when (property.returnType) {
String::class.createType() -> property.setter.call(config, value)
Boolean::class.createType() -> property.setter.call(config, value.toBoolean())
Int::class.createType() -> property.setter.call(config, value.toInt())
}
}
}
}
}
fun main() {
val map = mapOf(
"app.name" to "MyApp",
"app.version" to "1.0.0",
"app.debug" to "true"
)
val config = AppConfig()
loadConfig(config, map)
println("App: ${config.appName}, Version: ${config.version}, Debug: ${config.debug}")
// App: MyApp, Version: 1.0.0, Debug: true
}
第三章 协程深入
3.1 Channel 与 Fan-out/Fan-in
题目: 实现生产者-消费者模式,多个消费者从同一个 Channel 读取,实现 Fan-out(分发)和 Fan-in(合并)。
答案:
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun CoroutineScope.producer(channel: SendChannel<Int>) {
for (i in 1..5) {
delay(100)
channel.send(i * i)
}
channel.close()
}
fun main() = runBlocking {
// Fan-out: 多个消费者从同一 Channel 读取
val channel = produce<Int> {
for (i in 1..5) {
delay(100)
send(i)
}
close()
}
// 启动两个消费者
launch { for (v in channel) println("Consumer1: $v") }
launch { for (v in channel) println("Consumer2: $v") }.join()
// Fan-in: 多个生产者发送到同一 Channel
val merged = GlobalScope.produce<Int> {
val c1 = produce { for (i in 1..3) send(i) }
val c2 = produce { for (i in 4..6) send(i) }
merge(c1, c2).collect { send(it) }
}
println("Merged: ${merged.toList()}")
// Buffer Channel
val buffered = Channel<Int>(Channel.BUFFERED)
launch {
repeat(5) { buffered.send(it) }
}
launch {
delay(50)
buffered.receive()
buffered.receive()
}
}
3.2 Select 表达式
题目: 使用 select 同时等待多个协程结果,实现超时控制和时间最早的响应。
答案:
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.selects.*
suspend fun fetchFromAPI(name: String, delayMs: Long): String {
delay(delayMs)
return "$name result"
}
fun main() = runBlocking {
// 等待最快的响应
val result = select<String> {
launch { fetchFromAPI("fast", 100).also { println("fast ready") } .onJoin {
onSelect { "fast" }
} }
fetchFromAPI("slow", 500).onAwait { result ->
onSelect { result }
}
}
println("First: $result") // fast
// 超时控制
val withTimeout = withTimeoutOrNull(200) {
select {
fetchFromAPI("api1", 100).onAwait { it }
fetchFromAPI("api2", 300).onAwait { it }
}
}
println("Timeout result: $withTimeout") // null (都超时)
// Channel select
val ch1 = Channel<Int>()
val ch2 = Channel<Int>()
launch { ch1.send(1) }
launch { ch2.send(2) }
val received = select<Int> {
ch1.onReceive { it }
ch2.onReceive { it }
}
println("Received: $received")
}
3.3 Flow 高级操作
题目: 实现自定义 Flow 操作符 distinctUntilChanged,仅在值变化时发射;实现 scan 操作。
答案:
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
// distinctUntilChanged: 只发射与前一个不同的值
fun <T> Flow<T>.distinctUntilChanged(): Flow<T> = flow {
var previous: T? = null
collect { value ->
if (value != previous) {
previous = value
emit(value)
}
}
}
// 自定义中间操作符
fun <T, R> Flow<T>.mapNotNull(transform: suspend (T) -> R?): Flow<R> = flow {
collect { value ->
transform(value)?.let { emit(it) }
}
}
// 自定义终端操作符
suspend fun <T> Flow<T>.firstOrFail(message: String): T {
var result: T? = null
collect { result = it }
return result ?: throw IllegalStateException(message)
}
fun main() = runBlocking {
// 测试 distinctUntilChanged
flowOf(1, 1, 2, 2, 2, 3, 1)
.distinctUntilChanged()
.collect { print("$it ") } // 1 2 3 1
println()
// scan: 累积操作
flowOf(1, 2, 3, 4)
.scan(0) { acc, value -> acc + value }
.collect { print("$it ") } // 0 1 3 6 10
println()
// combineLatest
val nameFlow = flowOf("Alice", "Bob", "Carol")
val ageFlow = flowOf(25, 30)
combine(nameFlow, ageFlow) { name, age ->
"$name is $age"
}.collect { println(it) }
}
3.4 共享状态与并发安全
题目: 实现线程安全的计数器,使用 Mutex、AtomicInt 和 Channel 三种方式。
答案:
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
import java.util.concurrent.atomic.*
// 方式1: Mutex
suspend fun counterWithMutex(init: Int = 0): Int {
var count = init
val mutex = Mutex()
coroutineScope {
repeat(1000) {
launch {
mutex.withLock {
count++
}
}
}
}
return count
}
// 方式2: AtomicInt
suspend fun counterWithAtomic(): Int {
val count = AtomicInteger(0)
coroutineScope {
repeat(1000) {
launch {
count.incrementAndGet()
}
}
}
return count.get()
}
// 方式3: Channel 作为信号量
suspend fun counterWithChannel(): Int {
var count = 0
val channel = Channel<Unit>(Channel.CONFLATED)
coroutineScope {
repeat(1000) {
launch { channel.send(Unit) }
}
repeat(1000) {
channel.receive()
count++
}
}
return count
}
fun main() = runBlocking {
println("Mutex: ${counterWithMutex()}")
println("Atomic: ${counterWithAtomic()}")
println("Channel: ${counterWithChannel()}")
// Actor 模式
val counterActor = GlobalScope.actor<Int> {
var count = 0
channel.consumeEach {
count += it
if (count >= 10) {
println("Count reached $count")
}
}
}
repeat(10) { counterActor.offer(1) }
}
第四章 委托机制
4.1 委托属性基础
题目: 实现一个懒加载属性委托 lazy,模拟其实现方式。
答案:
kotlin
import kotlin.reflect.*
// 自定义懒加载委托
class Lazy<T>(initializer: () -> T) {
private var initializer: (() -> T)? = initializer
private var _value: Any? = null
private var initialized = false
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
if (!initialized) {
_value = initializer!!()
initialized = true
initializer = null
}
@Suppress("UNCHECKED_CAST")
return _value as T
}
}
class Person {
val name: String by Lazy {
println("Computing name...") // 只打印一次
"Alice"
}
}
fun main() {
val p = Person()
println("Created")
println(p.name) // Computing name... / Alice
println(p.name) // 直接返回 Alice(不再计算)
// 标准库 lazy
val lazyValue: String by lazy {
println("Lazy init")
"Computed"
}
println(lazyValue) // Lazy init / Computed
println(lazyValue) // Computed
}
4.2 Observable 与 Vetoable
题目: 实现 observable 委托,在值变化时打印旧值和新值;实现 vetoable,仅当新值满足条件时才更新。
答案:
kotlin
import kotlin.properties.*
import kotlin.reflect.*
// observable: 每次赋值后调用回调
class ObservableVar<T>(initial: T, val onChange: (T) -> Unit) {
private var value = initial
operator fun getValue(thisRef: Any?, property: KProperty<*>) = value
operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) {
println("${property.name}: $value -> $newValue")
value = newValue
onChange(newValue)
}
}
// vetoable: 回调返回 true 才接受新值
class VetoableVar<T>(initial: T, val predicate: (T) -> Boolean) {
private var value = initial
operator fun getValue(thisRef: Any?, property: KProperty<*>) = value
operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T): Boolean {
return if (predicate(newValue)) {
println("${property.name}: $value -> $newValue (accepted)")
value = newValue
true
} else {
println("${property.name}: $newValue rejected (predicate failed)")
false
}
}
}
class User {
var name: String by ObservableVar("Unknown") { newValue ->
println("User name changed to: $newValue")
}
var age: Int by ObservableVar(0) { println("Age updated: $it") }
}
fun main() {
val user = User()
user.name = "Alice" // name: Unknown -> Alice
user.name = "Bob" // name: Alice -> Bob
user.age = 25 // Age updated: 25
// vetoable
var score: Int by VetoableVar(0) { it in 0..100 }
score = 50 // score: 0 -> 50 (accepted)
score = 150 // score: 150 rejected (predicate failed)
println(score) // 50
}
4.3 委托类实现
题目: 实现 ReadOnlyMap 委托,允许通过属性访问 Map 的值。
答案:
kotlin
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.*
class MapDelegate<K, V>(private val map: Map<K, V>) : ReadOnlyProperty<Any?, V> {
override operator fun getValue(thisRef: Any?, property: KProperty<*>): V {
val key = property.name
return map[key as? K] ?: throw IllegalStateException("Key $key not found")
}
}
// 便捷函数
fun <K, V> mapDelegate(map: Map<K, V>) = MapDelegate(map)
class Config {
private val settings = mapOf(
"host" to "localhost",
"port" to 8080,
"debug" to true
)
val host: String by MapDelegate(settings)
val port: Int by MapDelegate(settings)
val debug: Boolean by MapDelegate(settings)
}
fun main() {
val config = Config()
println(config.host) // localhost
println(config.port) // 8080
println(config.debug) // true
// 使用扩展函数
val user = UserData(mapOf("name" to "Alice", "age" to "30"))
println(user.name) // Alice
println(user.age) // 30
}
class UserData(private val props: Map<String, String>) {
val name: String by mapDelegate(props)
val age: String by mapDelegate(props)
}
4.4 委托与懒加载工厂
题目: 实现类委托,使用 by 关键字将接口实现委托给另一个对象。
答案:
kotlin
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() = println("BaseImpl: $x")
}
// 类委托:Delegate 将接口实现委托给 impl
class Derived(b: Base) : Base by b
interface Collection<T> {
fun isEmpty(): Boolean
}
class ListCollection<T>(private val list: List<T>) : Collection<T> by list
fun main() {
val base = BaseImpl(42)
val derived = Derived(base)
derived.print() // BaseImpl: 42
val coll: Collection<Int> = ListCollection(listOf(1, 2, 3))
println(coll.isEmpty()) // false
}
第五章 设计模式
5.1 单例模式
题目: 使用 Kotlin 实现线程安全的单例,包括饿汉式、懒汉式(双重检查)、Bill Pugh Singleton。
答案:
kotlin
// 方式1: object 单例(Kotlin 原生支持)
object Singleton1 {
fun greet() = "I am Singleton1"
}
// 方式2: 懒汉式(双重检查锁)
class Singleton2 private constructor() {
companion object {
@Volatile private var instance: Singleton2? = null
fun getInstance(): Singleton2 {
return instance ?: synchronized(this) {
instance ?: Singleton2().also { instance = it }
}
}
}
}
// 方式3: 懒汉式(线程局部)
class Singleton3 private constructor() {
companion object {
val instance: Singleton3 by lazy { Singleton3() }
}
}
// 方式4: 枚举单例(防止反射攻击)
enum class Singleton4 {
INSTANCE;
fun greet() = "I am enum singleton"
}
fun main() {
println(Singleton1.greet()) // I am Singleton1
val s2a = Singleton2.getInstance()
val s2b = Singleton2.getInstance()
println(s2a === s2b) // true
val s3a = Singleton3.instance
val s3b = Singleton3.instance
println(s3a === s3b) // true
println(Singleton4.INSTANCE.greet()) // I am enum singleton
}
5.2 工厂模式与 Builder
题目: 使用 Kotlin 实现工厂模式,并结合 DSL 实现 Person 的 Builder。
答案:
kotlin
// 工厂方法
sealed class Result {
data class Success<T>(val data: T) : Result()
data class Error(val message: String) : Result()
}
class ResultFactory {
fun <T> success(data: T): Result.Success<T> = Result.Success(data)
fun error(message: String): Result.Error = Result.Error(message)
}
// Person Builder
class Person private constructor(
val name: String,
val age: Int,
val email: String?,
val address: String?
) {
class Builder {
private var name: String = ""
private var age: Int = 0
private var email: String? = null
private var address: String? = null
fun name(name: String) = apply { this.name = name }
fun age(age: Int) = apply { this.age = age }
fun email(email: String?) = apply { this.email = email }
fun address(address: String?) = apply { this.address = address }
fun build(): Person {
require(name.isNotBlank()) { "Name required" }
return Person(name, age, email, address)
}
}
}
// DSL 风格 Builder
class PersonDsl {
var name: String = ""
var age: Int = 0
var email: String? = null
var address: String? = null
fun build() = Person(name, age, email, address)
}
fun person(init: PersonDsl.() -> Unit) = PersonDsl().apply(init).build()
fun main() {
// 工厂模式
val factory = ResultFactory()
val success: Result<Int> = factory.success(42)
val error: Result<String> = factory.error("Not found")
// Builder 模式
val person1 = Person.Builder()
.name("Alice")
.age(30)
.email("alice@example.com")
.build()
println("${person1.name}, ${person1.age}, ${person1.email}")
// DSL Builder
val person2 = person {
name = "Bob"
age = 25
email = "bob@example.com"
}
println("${person2.name}, ${person2.age}")
}
5.3 策略模式与模板方法
题目: 使用 Lambda 和高阶函数实现策略模式,用扩展函数实现模板方法。
答案:
kotlin
// 策略模式:使用 Lambda
class PaymentProcessor {
fun pay(amount: Double, strategy: (Double) -> Boolean) {
if (strategy(amount)) {
println("Payment of $$amount succeeded")
} else {
println("Payment failed")
}
}
}
val creditCardStrategy: (Double) -> Boolean = { amount ->
println("Processing credit card...")
amount <= 1000
}
val paypalStrategy: (Double) -> Boolean = { amount ->
println("Processing PayPal...")
amount <= 5000
}
fun main() {
val processor = PaymentProcessor()
processor.pay(500.0, creditCardStrategy) // Processing credit card... / succeeded
processor.pay(6000.0, paypalStrategy) // Processing PayPal... / failed
// 模板方法:定义骨架,具体实现延迟到子类
abstract class DataProcessor {
fun process() {
val data = readData()
val cleaned = cleanData(data)
val result = analyze(cleaned)
saveResult(result)
}
abstract fun readData(): String
abstract fun cleanData(data: String): String
abstract fun analyze(data: String): String
open fun saveResult(result: String) {
println("Saving: $result")
}
}
class TextProcessor : DataProcessor() {
override fun readData() = "raw text data"
override fun cleanData(data: String) = data.trim()
override fun analyze(data: String) = data.uppercase()
}
TextProcessor().process()
}
第六章 内联类与值类
6.1 内联类基础
题目: 定义内联类 UserId 和 OrderId,实现类型安全的长度度量。
答案:
kotlin
// 内联类:运行时零开销,编译时提供类型安全
inline class UserId(val value: String)
inline class OrderId(val value: String)
inline class Meters(val value: Double) {
operator fun plus(other: Meters) = Meters(value + other.value)
override fun toString() = "${value}m"
}
inline class PositiveInt(val value: Int) {
init {
require(value > 0) { "Must be positive" }
}
}
fun main() {
val userId = UserId("user-123")
val orderId = OrderId("order-456")
println(userId.value) // user-123
println(userId == orderId) // false (类型不同,虽值相同)
val length = Meters(5.0)
val width = Meters(3.0)
println(length + width) // 8.0m
val pos = PositiveInt(10)
println(pos.value) // 10
// PositiveInt(-1) // IllegalArgumentException: Must be positive
}
6.2 内联类与类型别名
题目: 说明内联类和类型别名的区别,以及各自的适用场景。
答案:
kotlin
// 类型别名:运行时还是同一类型,无类型安全
typealias UserName = String
typealias Email = String
fun sendEmail(email: Email, message: String) {
println("Sending to $email: $message")
}
// 内联类:编译时是不同类型,有类型安全
inline class Password(val value: String)
inline class Token(val value: String)
fun authenticate(token: Token) {
println("Authenticating with token: ${token.value}")
}
fun main() {
val name: UserName = "Alice"
val email: Email = "alice@example.com"
// 类型别名:String 和 String 可互换
sendEmail(name, "Hello") // 可以,String 可赋值给 Email
// 内联类:类型安全,不会混淆
val token = Token("abc123")
authenticate(token)
// Token("abc") != Password("abc") (编译期错误)
// 适用场景:
// - 类型别名:内部使用,不暴露给外部 API
// - 内联类:公开 API,需要类型安全防止误用
}
第七章 性能与优化
7.1 集合操作性能
题目: 比较不同集合操作的时间复杂度,选择合适的数据结构实现高效查找。
答案:
kotlin
fun main() {
// 列表查找:O(n)
val list = List(100000) { it }
println(list.contains(99999)) // true
// Set 查找:O(1)
val set = list.toSet()
println(set.contains(99999)) // true
// Map 查找:O(1)
val map = list.associateWith { "value_$it" }
println(map[99999]) // value_99999
// 避免:list.filter { condition }.firstOrNull() 效率低
// 正确:list.firstOrNull { condition }
// 批量操作
val numbers = (1..100000).toList()
// 差: 多次遍历
val result1 = numbers.map { it * 2 }.filter { it > 100 }.take(10)
// 好: 一次遍历
val result2 = numbers.asSequence()
.map { it * 2 }
.filter { it > 100 }
.take(10)
.toList()
// Sequence(懒加载)在大数据集时更优
println(result2) // [102, 104, 106, ...]
// 使用 groupBy 而非手动分组
val grouped = numbers.groupBy { it % 10 }
println(grouped[0]?.last()) // 99990
}
7.2 内联函数与对象分配
题目: 说明 inline 函数何时能提升性能,何时会适得其反。
答案:
kotlin
// 适合内联的场景:Lambda 参数,创建新作用域
inline fun <T> measureTime(block: () -> T): T {
val start = System.currentTimeMillis()
val result = block()
println("Elapsed: ${System.currentTimeMillis() - start}ms")
return result
}
// 不适合内联的场景:Lambda 传递给其他函数(非局部返回)
inline fun foo(inlined: () -> Unit, crossinline notInlined: () -> Unit) {
inlined()
notInlined()
}
// reified 内联函数
inline fun <reified T> getTypeName() = T::class.simpleName
fun main() {
// 适合内联
val result = measureTime {
Thread.sleep(10)
"done"
}
// reified 获取类型
println(getTypeName<String>()) // String
println(getTypeName<Int>()) // Int
// 内联的反面:代码膨胀
// inline 不适合的场景:
// - 函数体大
// - 调用次数少(减少代码复用性)
// - 递归函数
// - 参数中有非内联 Lambda
}
第八章 协程与 Flow 实战
8.1 协程取消与超时
题目: 实现一个可取消的任务,使用 withTimeout 和 withTimeoutOrNull,并处理 CancellationException。
答案:
kotlin
import kotlinx.coroutines.*
fun main() = runBlocking {
// withTimeout: 超时抛出异常
try {
withTimeout(100) {
repeat(1000) { i ->
println("Task $i")
delay(10)
}
}
} catch (e: TimeoutCancellationException) {
println("Timed out!")
}
// withTimeoutOrNull: 超时返回 null
val result = withTimeoutOrNull(100) {
repeat(1000) { i ->
println("Task $i")
delay(10)
}
"Completed"
}
println("Result: $result") // null
// 协程取消:检查 isActive
val job = launch {
try {
repeat(1000) { i ->
if (!isActive) {
println("Cancelled at $i")
break
}
println("Working $i")
delay(5)
}
} finally {
// 清理代码一定会执行
println("Cleanup!")
}
}
delay(50)
println("Cancelling...")
job.cancelAndJoin()
println("Cancelled")
}
8.2 Flow 异常处理
题目: 实现 Flow 的错误处理,使用 catch、retry 和 onEach 转换错误。
答案:
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
// catch: 捕获上游异常
flow {
emit(1)
emit(2)
throw RuntimeException("Error!")
}.catch { e ->
println("Caught: ${e.message}")
emit(-1) // 发出替代值
}.collect { println(it) } // 1, 2, -1
// retry: 自动重试
var attempts = 0
flow {
attempts++
if (attempts < 3) throw RuntimeException("Retry $attempts")
emit("Success!")
}.retry(3) { e ->
println("Retrying: ${e.message}")
true // 重试条件
}.catch { e ->
println("All retries failed: ${e.message}")
}.collect { println(it) }
// onEach / onCompletion
flowOf(1, 2, 3, 4, 5)
.onEach { if (it == 3) throw RuntimeException("Bad number") }
.onEach { println("Processing $it") }
.catch { println("Error: ${it.message}") }
.onCompletion { println("Flow completed") }
.collect { }
// 决赛选手模式:combineTransform
val f1 = flowOf(1, 2, 3)
val f2 = flowOf("a", "b")
combine(f1, f2) { num, str -> "$str$num" }
.onEach { println(it) }
.launchIn(this)
delay(100)
}
答案汇总索引
| 章节 | 题目 | 核心知识点 |
|---|---|---|
| 1.1-1.2 | DSL | 类型安全构建器、接收者类型、Lambda DSL |
| 2.1-2.2 | 反射 | KProperty、data class 反射、注解处理 |
| 3.1-3.4 | 协程深入 | Channel、Select、Flow 高级、并发安全 |
| 4.1-4.4 | 委托 | 委托属性、observable、vetoable、类委托 |
| 5.1-5.3 | 设计模式 | 单例、工厂、Builder、策略、模板方法 |
| 6.1-6.2 | 内联类 | 值类、类型安全、类型别名对比 |
| 7.1-7.2 | 性能 | 集合复杂度、Sequence、内联优化 |
| 8.1-8.2 | 协程实战 | 取消超时、Flow 异常处理、重试 |
恭喜完成 Kotlin 全套习题!持续练习,编码能力更进一步 🚀