跳转至

第 03 章 Kotlin 语言核心特性

Kotlin 语言核心特性图

学习目标:全面掌握 Kotlin 语言的核心特性,理解其在 Android 开发中的最佳实践。

预计学习时间: 3-5 天 实践时间: 2 天


目录

  1. Kotlin 与 Java 对比
  2. 空安全系统
  3. 类型系统与泛型
  4. 函数与 Lambda
  5. 协程与异步编程
  6. 面向对象与函数式编程
  7. DSL 构建
  8. Kotlin 2.0 与 K2 编译器
  9. 实践练习

1. Kotlin 与 Java 对比

1.1 为什么选择 Kotlin

特性 Kotlin Java
空安全 编译期检查 运行时异常
简洁性 减少 40%样板代码 冗长
函数式编程 一等公民支持 Java 8+部分支持
协程 原生支持 需第三方库
扩展函数 支持 不支持
默认参数 支持 需重载
数据类 一行定义 需手写 getter/setter
类型推导 强大 有限

1.2 代码对比示例

Java 代码

Java
// Java - 数据类
public class User {
    private final String name;
    private final int age;
    private final String email;

    public User(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }

    // Getter方法
    public String getName() { return name; }
    public int getAge() { return age; }
    public String getEmail() { return email; }

    // equals, hashCode, toString
    @Override  // @Override重写父类方法
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age &&
               Objects.equals(name, user.name) &&
               Objects.equals(email, user.email);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, email);
    }

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + ", email='" + email + "'}";
    }
}

// Java - 单例模式
public class DatabaseHelper {
    private static DatabaseHelper instance;

    private DatabaseHelper() {}

    public static synchronized DatabaseHelper getInstance() {  // synchronized同步锁,保证线程安全
        if (instance == null) {
            instance = new DatabaseHelper();
        }
        return instance;
    }
}

Kotlin 代码

Kotlin
// Kotlin - 数据类(一行搞定)
data class User(
    val name: String,
    val age: Int,
    val email: String
)

// Kotlin - 单例模式
object DatabaseHelper {
    // 自动线程安全
}

// Kotlin - 空安全
fun greet(user: User?) {
    // 安全调用
    val name = user?.name ?: "Guest"
    println("Hello, $name!")
}

// Kotlin - 扩展函数
fun String.addExclamation(): String = this + "!"
val greeting = "Hello".addExclamation() // "Hello!"

// Kotlin - 默认参数
fun createUser(
    name: String,
    age: Int = 18,
    email: String = ""
): User = User(name, age, email)

// 调用时可以省略默认参数
val user1 = createUser("Alice")
val user2 = createUser("Bob", 25)
val user3 = createUser("Charlie", 30, "charlie@example.com")

2. 空安全系统

2.1 可空类型与非空类型

Kotlin
// 非空类型(默认)
var name: String = "Alice"
// name = null // 编译错误!

// 可空类型(显式声明)
var nickname: String? = "Ally"
nickname = null // 允许

// 安全调用操作符 ?.
val length = nickname?.length // 如果nickname为null,返回null

// Elvis操作符 ?:
val displayName = nickname ?: "Unknown" // 如果为null,使用默认值

// 非空断言 !!(谨慎使用)
val riskyLength = nickname!!.length // 如果为null,抛出NPE

// 安全转换 as?
val obj: Any = "Hello"
val str: String? = obj as? String // 如果转换失败,返回null

2.2 空安全最佳实践

Kotlin
// ✅ 推荐:使用安全调用和Elvis操作符
fun processUser(user: User?) {
    val name = user?.name ?: return
    val email = user.email ?: throw IllegalArgumentException("Email required")

    println("Processing $name with email $email")
}

// ✅ 推荐:使用let进行空检查
user?.let { nonNullUser ->
    // 在这个作用域内,nonNullUser是非空的
    println(nonNullUser.name)
    println(nonNullUser.email)
}

// ✅ 推荐:使用also进行副作用操作
user?.also {
    analytics.trackUserView(it.id)
}?.let { process(it) }

// ❌ 避免:滥用非空断言
val length = text!!.length // 危险!

// ❌ 避免:不必要的空检查
if (user != null) {
    println(user.name) // 可以用?.let替代
}

2.3 平台类型(与 Java 互操作)

Kotlin
// Java代码返回的可空类型需要特别注意
val javaString: String = javaObject.getString() // 可能运行时NPE
val safeString: String? = javaObject.getString() // 更安全

// 使用@Nullable/@NonNull注解
// Java:
// @NonNull
// public String getName() { ... }

// Kotlin会自动识别
val name: String = javaObject.name // 非空

3. 类型系统与泛型

3.1 类型推导

Kotlin
// 显式类型声明
val name: String = "Alice"

// 类型推导
val age = 25 // 自动推导为Int
val price = 19.99 // 自动推导为Double
val isActive = true // 自动推导为Boolean

// 复杂类型推导
val users = listOf(
    User("Alice", 25),
    User("Bob", 30)
) // 自动推导为 List<User>

// 泛型类型推导
fun <T> singletonList(item: T): List<T> = listOf(item)
val stringList = singletonList("hello") // 推导为 List<String>

3.2 泛型进阶

Kotlin
// 协变(Covariant)- out
interface Producer<out T> {
    fun produce(): T
    // 不能消费T
}

val stringProducer: Producer<String> = object : Producer<String> {
    override fun produce(): String = "Hello"
}
val anyProducer: Producer<Any> = stringProducer // 允许,因为String是Any的子类

// 逆变(Contravariant)- in
interface Consumer<in T> {
    fun consume(item: T)
    // 不能生产T
}

val anyConsumer: Consumer<Any> = object : Consumer<Any> {
    override fun consume(item: Any) = println(item)
}
val stringConsumer: Consumer<String> = anyConsumer // 允许

// 不变(Invariant)- 默认
interface Container<T> {
    fun produce(): T
    fun consume(item: T)
}

// 类型投影(Use-site variance)
fun copy(from: Array<out Any>, to: Array<Any>) {
    // from是协变的,只能读取
}

fun fill(dest: Array<in String>, value: String) {
    // dest是逆变的,只能写入
}

3.3 类型约束

Kotlin
// 上界约束
fun <T : Comparable<T>> max(a: T, b: T): T {
    return if (a > b) a else b
}

// 多个约束
fun <T> process(item: T) where T : Runnable, T : Serializable {
    item.run()
}

// 具体化类型参数(reified)
inline fun <reified T> isInstance(value: Any): Boolean {
    return value is T
}

// 使用
val isString = isInstance<String>("hello") // true
val isInt = isInstance<Int>("hello") // false

4. 函数与 Lambda

4.1 函数定义与特性

Kotlin
// 基本函数
fun greet(name: String): String {
    return "Hello, $name!"
}

// 单表达式函数
fun greet(name: String): String = "Hello, $name!"

// 默认参数
fun greet(name: String, greeting: String = "Hello"): String {
    return "$greeting, $name!"
}

// 命名参数
greet(name = "Alice", greeting = "Hi")
greet(greeting = "Hey", name = "Bob")

// 可变参数
fun sum(vararg numbers: Int): Int {
    return numbers.sum()
}
sum(1, 2, 3, 4, 5)

// 展开操作符
val nums = intArrayOf(1, 2, 3)
sum(*nums) // 展开数组

4.2 高阶函数

Kotlin
// 函数作为参数
fun processNumbers(
    numbers: List<Int>,
    transformer: (Int) -> Int
): List<Int> {
    return numbers.map(transformer)
}

// 使用
val doubled = processNumbers(listOf(1, 2, 3)) { it * 2 }

// 函数作为返回值
fun createMultiplier(factor: Int): (Int) -> Int {
    return { number -> number * factor }
}

val triple = createMultiplier(3)
println(triple(4)) // 12

// 函数类型
val operation: (Int, Int) -> Int = { a, b -> a + b }

4.3 Lambda 表达式

Kotlin
// 基本Lambda
val sum = { a: Int, b: Int -> a + b }

// 类型推导
val multiply: (Int, Int) -> Int = { a, b -> a * b }

// 单个参数(隐式it)
val square: (Int) -> Int = { it * it }

// 多语句Lambda
val process = { x: Int ->
    val doubled = x * 2
    val result = doubled + 10
    result // 最后一行是返回值
}

// 集合操作中的Lambda
val numbers = listOf(1, 2, 3, 4, 5)

// filter
val evens = numbers.filter { it % 2 == 0 }

// map
val squares = numbers.map { it * it }

// reduce
val sum = numbers.reduce { acc, i -> acc + i }

// fold
val product = numbers.fold(1) { acc, i -> acc * i }

// groupBy
val grouped = numbers.groupBy { it % 2 }

// sortedBy
val sorted = numbers.sortedByDescending { it }

// takeWhile
val firstThree = numbers.takeWhile { it < 4 }

4.4 作用域函数

Kotlin
// let - 转换对象,返回Lambda结果
val nameLength = user.name?.let {
    it.uppercase()
    it.length
}

// run - 执行代码块,返回Lambda结果
val result = user.run {
    println("Processing $name")
    process(this)
    name.length
}

// with - 对对象执行多个操作
with(user) {
    println(name)
    println(email)
    updateLastSeen()
}

// apply - 配置对象,返回对象本身
val dialog = AlertDialog.Builder(context).apply {
    setTitle("Confirm")
    setMessage("Are you sure?")
    setPositiveButton("Yes") { _, _ -> }
    setNegativeButton("No", null)
}.create()

// also - 执行副作用,返回对象本身
val file = File("data.txt").also {
    println("Creating file: ${it.name}")
    it.createNewFile()
}

// 对比总结
// let/run/with: 返回Lambda结果
// apply/also: 返回接收者对象
// let/also: 使用it
// run/apply/with: 使用this

5. 协程与异步编程

5.1 协程基础

Kotlin
import kotlinx.coroutines.*

// 启动协程
fun main() = runBlocking {
    // launch - 启动新协程,不阻塞,返回Job
    val job = launch {
        delay(1000L)
        println("World!")
    }

    println("Hello,")
    job.join() // 等待协程完成

    // async - 启动新协程,返回Deferred(可获取结果)
    val deferred = async {
        delay(1000L)
        "Result"
    }

    val result = deferred.await() // 获取结果
    println(result)
}

// 协程作用域
class MyViewModel : ViewModel() {
    fun fetchData() {
        viewModelScope.launch {
            // 在ViewModel作用域中启动协程
            // 当ViewModel清除时自动取消
        }
    }
}

// 自定义作用域
val scope = CoroutineScope(Dispatchers.Main + Job())

scope.launch {
    // 在自定义作用域中执行
}

// 取消作用域
scope.cancel()

5.2 调度器( Dispatchers )

Kotlin
// Dispatchers.Main - 主线程(UI操作)
launch(Dispatchers.Main) {
    updateUI()
}

// Dispatchers.IO - 磁盘/网络IO
launch(Dispatchers.IO) {
    val data = fetchFromNetwork()
}

// Dispatchers.Default - CPU密集型任务
launch(Dispatchers.Default) {
    val result = heavyComputation()
}

// Dispatchers.Unconfined - 不限制,从调用线程开始
launch(Dispatchers.Unconfined) {
    // 特殊用途,一般不使用
}

// 切换调度器
launch(Dispatchers.Main) {
    val data = withContext(Dispatchers.IO) {
        // 在IO线程执行
        fetchData()
    }
    // 回到主线程
    displayData(data)
}

5.3 Flow - 响应式流

Kotlin
import kotlinx.coroutines.flow.*

// 创建Flow
val numberFlow: Flow<Int> = flow {
    for (i in 1..5) {
        delay(100)
        emit(i) // 发射值
    }
}

// 收集Flow
lifecycleScope.launch {
    numberFlow.collect { value ->
        println(value)
    }
}

// Flow操作符
val processedFlow = numberFlow
    .map { it * it } // 转换
    .filter { it > 10 } // 过滤
    .onEach { println("Processing: $it") } // 副作用
    .catch { e -> println("Error: $e") } // 错误处理
    .flowOn(Dispatchers.IO) // 指定执行调度器

// StateFlow - 状态流(热流)
class MyViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(UiState())
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()

    fun updateState(newState: UiState) {
        _uiState.value = newState
    }
}

// SharedFlow - 共享流(热流)
class EventBus {
    private val _events = MutableSharedFlow<Event>()
    val events = _events.asSharedFlow()

    suspend fun emit(event: Event) {
        _events.emit(event)
    }
}

// 在Compose中收集
@Composable
fun MyScreen(viewModel: MyViewModel) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    // 使用uiState更新UI
}

5.4 异常处理

Kotlin
// try-catch
launch {
    try {
        riskyOperation()
    } catch (e: Exception) {
        println("Error: ${e.message}")
    }
}

// SupervisorJob - 子协程失败不影响其他
val supervisor = SupervisorJob()
val scope = CoroutineScope(Dispatchers.Main + supervisor)

scope.launch {
    // 子协程1
    launch {
        throw Exception("Failed")
    }

    // 子协程2 - 继续执行
    launch {
        delay(100)
        println("Still running")
    }
}

// CoroutineExceptionHandler
val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught $exception")
}

val scope = CoroutineScope(Dispatchers.Main + handler)
scope.launch {
    throw Exception("Error")
}

// Flow异常处理
flow {
    emit(1)
    throw Exception("Error")
    emit(2)
}.catch { e ->
    println("Caught: $e")
    emit(-1) // 发射默认值
}.collect {
    println(it)
}

6. 面向对象与函数式编程

6.1 类与继承

Kotlin
// 基本类
open class Person(
    val name: String,
    var age: Int
) {
    open fun introduce() {
        println("I'm $name, $age years old")
    }
}

// 继承
class Student(
    name: String,
    age: Int,
    val school: String
) : Person(name, age) {

    override fun introduce() {
        super.introduce()
        println("I study at $school")
    }
}

// 数据类
data class User(
    val id: String,
    val name: String,
    val email: String = "" // 默认参数
) {
    // 自动获得:equals, hashCode, toString, copy, componentN
}

// 使用数据类
val user1 = User("1", "Alice")
val user2 = user1.copy(name = "Bob") // 复制并修改
val (id, name, email) = user1 // 解构

// 密封类(Sealed Class)
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()  // 泛型<T>:类型参数化
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

// 使用密封类
fun handleResult(result: Result<String>) {
    when (result) {
        is Result.Success -> println("Data: ${result.data}")
        is Result.Error -> println("Error: ${result.exception}")
        Result.Loading -> println("Loading...")
    }
}

// 枚举类
enum class Status {
    PENDING,
    PROCESSING,
    COMPLETED,
    FAILED;

    fun isTerminal() = this == COMPLETED || this == FAILED
}

// 带属性的枚举
enum class Priority(val value: Int) {
    LOW(1),
    MEDIUM(2),
    HIGH(3)
}

6.2 接口与抽象类

Kotlin
// 接口
interface Drawable {
    fun draw()
    fun resize() { // 默认实现
        println("Default resize")
    }
}

interface Clickable {
    fun click()
}

// 实现多个接口
class Button : Drawable, Clickable {
    override fun draw() {
        println("Drawing button")
    }

    override fun click() {
        println("Button clicked")
    }
}

// 解决冲突
class CustomView : Drawable, Clickable {
    override fun draw() {
        super<Drawable>.resize() // 调用指定接口的默认实现
    }

    override fun click() {}
}

// 抽象类
abstract class Shape {
    abstract fun area(): Double

    fun printArea() {
        println("Area: ${area()}")
    }
}

class Circle(val radius: Double) : Shape() {
    override fun area(): Double = Math.PI * radius * radius
}

6.3 函数式编程特性

Kotlin
// 不可变性
val immutableList = listOf(1, 2, 3)
// immutableList.add(4) // 错误!

val mutableList = mutableListOf(1, 2, 3)
mutableList.add(4) // 允许

// 纯函数
fun pureAdd(a: Int, b: Int): Int = a + b // 无副作用,相同输入总是相同输出

// 不可变数据操作
val numbers = listOf(1, 2, 3, 4, 5)

// 不改变原列表,返回新列表
val doubled = numbers.map { it * 2 }
val evens = numbers.filter { it % 2 == 0 }
val sum = numbers.fold(0) { acc, n -> acc + n }

// 函数组合
fun <A, B, C> compose(
    f: (B) -> C,
    g: (A) -> B
): (A) -> C = { x -> f(g(x)) }

val addOne = { x: Int -> x + 1 }
val double = { x: Int -> x * 2 }
val addOneThenDouble = compose(double, addOne)

println(addOneThenDouble(3)) // (3 + 1) * 2 = 8

// 部分应用(Partial Application)
fun <A, B, C> ((A, B) -> C).partial(a: A): (B) -> C {
    return { b -> this(a, b) }
}

fun add(a: Int, b: Int) = a + b
val addFive = ::add.partial(5)
println(addFive(3)) // 8

// 柯里化(Currying)
fun <A, B, C> ((A, B) -> C).curry(): (A) -> (B) -> C {
    return { a -> { b -> this(a, b) } }
}

val curriedAdd = ::add.curry()
val addTen = curriedAdd(10)
println(addTen(5)) // 15

7. DSL 构建

7.1 类型安全构建器

Kotlin
// HTML DSL示例
abstract class Tag(val name: String) {
    val children = mutableListOf<Tag>()
    val attributes = mutableMapOf<String, String>()

    protected fun <T : Tag> initTag(tag: T, init: T.() -> Unit): T {
        tag.init()
        children.add(tag)
        return tag
    }

    override fun toString(): String {
        val attrs = if (attributes.isEmpty()) ""
                   else attributes.map { "${it.key}='${it.value}'" }.joinToString(" ", " ")
        val content = children.joinToString("")
        return "<$name$attrs>$content</$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(Text(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") {
    operator fun String.unaryPlus() {
        children.add(Text(this))
    }
}

class P : Tag("p") {
    operator fun String.unaryPlus() {
        children.add(Text(this))
    }
}

class Text(private val text: String) : Tag("") {
    override fun toString() = text
}

fun html(init: HTML.() -> Unit): HTML {
    val html = HTML()
    html.init()
    return html
}

// 使用DSL
val document = html {
    head {
        title { +"My Page" }
    }
    body {
        h1 { +"Welcome" }
        p { +"This is a DSL example" }
    }
}

println(document)
// 输出: <html><head><title>My Page</title></head><body><h1>Welcome</h1><p>This is a DSL example</p></body></html>

7.2 Gradle Kotlin DSL

Kotlin
// build.gradle.kts
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("org.jetbrains.kotlin.plugin.compose") // Kotlin 2.0+ Compose 编译器插件
}

android {
    namespace = "com.example.app"
    compileSdk = 35

    defaultConfig {
        applicationId = "com.example.app"
        minSdk = 24
        targetSdk = 35
        versionCode = 1
        versionName = "1.0"
    }

    buildTypes {
        release {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }

    buildFeatures {
        compose = true
    }
    // Kotlin 2.0+ 无需 composeOptions,Compose 编译器版本由 kotlin.plugin.compose 插件管理
}

dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.compose.ui:ui:1.5.4")

    // 使用lambda配置依赖
    val composeBom = platform("androidx.compose:compose-bom:2024.02.01")
    implementation(composeBom)
    androidTestImplementation(composeBom)
}

7.3 Compose UI DSL

Kotlin
// Jetpack Compose就是Kotlin DSL的完美示例
@Composable
fun MyScreen(viewModel: MyViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsState()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Text(
            text = "Hello, ${uiState.userName}!",
            style = MaterialTheme.typography.headlineMedium
        )

        Button(
            onClick = { viewModel.onRefresh() },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("Refresh")
        }

        when {
            uiState.isLoading -> CircularProgressIndicator()
            uiState.error != null -> ErrorMessage(uiState.error)
            else -> ContentList(uiState.items)
        }
    }
}

8. Kotlin 2.0 与 K2 编译器

8.1 K2 编译器简介

Kotlin 2.0 于 2024 年发布,引入了全新的 K2 编译器(代号 K2 ),这是 Kotlin 编译器的重大重构版本。 K2 编译器带来了显著的性能提升和语言特性增强。

主要改进

特性 改进幅度 说明
编译速度 提升 94% 编译 Kotlin 代码速度比原始编译器快近 2 倍
代码分析 大幅提升 高亮、补全、查找跳转速度显著改善
内存占用 降低 编译过程中内存使用效率更高
新语言特性 全面支持 支持 Kotlin 2.0 及以上版本的新特性

启用 K2 编译器

在 Android Studio Narwhal ( 2025.1.1 )及更高版本中, K2 模式已成为默认选项:

Kotlin
// gradle.properties
kotlin.experimental.tryK2=true

// 或者在build.gradle.kts中
kotlin {
    compilerOptions {
        languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0
    }
}

8.2 Kotlin 2.0 新特性

数据类的 copy 函数改进

Kotlin
// Kotlin 2.0之前 - 需要复制所有属性
data class User(
    val name: String,
    val age: Int,
    val email: String
)

val user = User("Alice", 30, "alice@example.com")
val updatedUser = user.copy(age = 31) // 其他属性保持不变

// Kotlin 2.0 - 支持在copy中使用命名参数
// 现在可以在copy中更灵活地处理默认值

枚举类中的数据对象

Kotlin
// Kotlin 2.0支持在密封类和枚举中使用数据对象
sealed interface Error  // interface定义类型契约

// 数据对象自动生成equals/hashCode/toString
data object NetworkError : Error
data object DatabaseError : Error
data class ValidationError(val field: String) : Error

更好的类型推导

Kotlin
// Kotlin 2.0改进了类型推导
val list = buildList {
    add("hello") // 自动推导为MutableList<String>
    add("world")
}

// Lambda返回类型推导改进
val transform = when (condition) {
    true -> { x: Int -> x * 2 }
    false -> { x: Int -> x + 1 }
} // 编译器能正确推导类型

8.3 Android Studio 集成

Android Studio Narwhal ( 2025.1.1 )及更高版本默认启用 K2 模式:

Text Only
Settings → Languages & Frameworks → Kotlin → K2 Kotlin Mode

注意事项: - K2 编译器与旧编译器在边缘情况下可能有不同行为 - 某些第三方插件可能需要更新以兼容 K2 - 建议在项目升级前进行充分测试

8.4 迁移指南

从 Kotlin 1.9 迁移到 2.0 的步骤:

  1. 更新 Gradle 插件
Kotlin
// build.gradle.kts (项目级)
plugins {
    id("com.android.application") version "8.5.0" apply false
    id("org.jetbrains.kotlin.android") version "2.0.0" apply false
}
  1. 更新编译器选项
Kotlin
// build.gradle.kts (模块级)
android {
    kotlinOptions {
        jvmTarget = "17"
        freeCompilerArgs += "-Xjdk-release=17"
    }
}
  1. 检查破坏性变更
  2. 某些反射 API 的行为可能有变化
  3. 类型推导的改进可能导致之前编译通过的代码需要调整

9. 实践练习

练习 1 :空安全重构

任务:将以下 Java 代码重构为 Kotlin ,确保空安全

Java
public class UserManager {
    private User currentUser;

    public String getUserDisplayName() {
        if (currentUser != null) {
            if (currentUser.getProfile() != null) {
                return currentUser.getProfile().getDisplayName();
            }
        }
        return "Guest";
    }

    public void updateEmail(String newEmail) {
        if (currentUser != null && newEmail != null) {
            currentUser.setEmail(newEmail);
        }
    }
}

要求: - 使用 Kotlin 的空安全特性 - 使用 Elvis 操作符和安全调用 - 减少代码行数

练习 2 :泛型容器实现

任务:实现一个类型安全的 Result 容器类

Kotlin
sealed class Result<out T> {
    // 实现Success和Error子类
    // 实现map、flatMap、getOrElse等方法
}

// 使用示例
fun fetchUser(id: String): Result<User> {
    return try {  // try/catch捕获异常
        val user = api.getUser(id)
        Result.Success(user)
    } catch (e: Exception) {
        Result.Error(e)
    }
}

// 链式操作
fetchUser("123")
    .map { it.name }
    .getOrElse { "Unknown" }

练习 3 :协程实践

任务:实现一个并行数据加载器

Kotlin
class DataLoader {
    suspend fun loadUserData(userId: String): UserData {
        // 并行加载用户基本信息、订单、设置
        // 使用async和await
        // 处理异常
    }
}

// 测试
runBlocking {
    val data = DataLoader().loadUserData("123")
    println(data)
}

练习 4 : DSL 设计

任务:设计一个网络请求 DSL

Kotlin
// 目标DSL
val request = httpRequest {
    url = "https://api.example.com/users"
    method = HttpMethod.GET
    headers {
        "Authorization" to "Bearer token"
        "Content-Type" to "application/json"
    }
    queryParams {
        "page" to "1"
        "limit" to "10"
    }
}

// 实现DSL构建器

本章小结

核心要点

  1. 空安全是 Kotlin 的核心特性,通过编译期检查避免 NPE
  2. 类型系统强大且灵活,支持泛型、类型推导和类型投影
  3. 函数是一等公民,支持高阶函数、 Lambda 和函数式编程
  4. 协程简化异步编程, Flow 提供响应式数据流
  5. DSL 构建能力使 Kotlin 成为构建领域特定语言的理想选择

Kotlin vs Java 速查

Java Kotlin
User user = new User() val user = User()
user.getName() user.name
user.setName("Alice") `user.name = "Alice"
if (obj instanceof String) if (obj is String)
(String) obj obj as String
switch when
System.out.println() println()
final val
new Thread(() -> {}).start() thread { }
try-catch-finally try-catch-finallyuse

下一步

完成本章学习后,请进入第 04 章: Jetpack Compose UI 框架详解,开始学习现代 Android UI 开发。


参考资源

官方文档

学习资源

进阶阅读


本章完成时间:预计 3-5 天