跳转至

第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
    }
    

  2. 更新编译器选项

    Kotlin
    // build.gradle.kts (模块级)
    android {
        kotlinOptions {
            jvmTarget = "17"
            freeCompilerArgs += "-Xjdk-release=17"
        }
    }
    

  3. 检查破坏性变更

  4. 某些反射API的行为可能有变化
  5. 类型推导的改进可能导致之前编译通过的代码需要调整

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天