Java 转 Kotlin 对照开发指南

Java 转 Kotlin 对照开发指南

一、基本类型对照表

|-----------------|-------------------|------------|----------------------|--------------------------|
| Java 类型 | Kotlin 类型 | 说明 | Java 示例 | Kotlin 示例 |
| int | Int | 整型 | int num = 10; | val num: Int = 10 |
| long | Long | 长整型 | long bigNum = 100L; | val bigNum: Long = 100L |
| double | Double | 双精度浮点 | double price = 9.99; | val price: Double = 9.99 |
| float | Float | 单精度浮点 | float pi = 3.14f; | val pi: Float = 3.14f |
| boolean | Boolean | 布尔型 | boolean flag = true; | val flag: Boolean = true |
| char | Char | 字符 | char c = 'A'; | val c: Char = 'A' |
| String | String | 字符串 | String name = "Tom"; | val name: String = "Tom" |
| Integer | Int? | 可空整型 | Integer num = null; | val num: Int? = null |

二、变量声明对照

|--------------------------------------------|--------------------------------------|------------|
| Java 写法 | Kotlin 写法 | 说明 |
| int x = 5; | val x: Int = 5 | 不可变变量 |
| String name = "John"; | var name: String = "John" | 可变变量 |
| final int MAX = 100; | const val MAX = 100 | 编译时常量 |
| List<String> list = new ArrayList<>(); | val list = mutableListOf<String>() | 集合初始化 |

三、控制流对照

1. 条件语句

java 复制代码
// Java

if (score >= 60) {
    System.out.println("及格");
} else {
    System.out.println("不及格");
}
Kotlin 复制代码
// Kotlin

if (score >= 60) {

    println("及格")

} else {

    println("不及格")

}
// 或作为表达式
val result = if (score >= 60) "及格" else "不及格"

2. 循环语句

java 复制代码
// Java for循环
for (int i = 0; i < 10; i++) {

    System.out.println(i);

}


// Kotlin for循环
for (i in 0..9) {

    println(i)
}

// 或
for (i in 0 until 10) {

    println(i)

}

四、函数/方法对照

|--------------------------------------------------------------------------------|----------------------------------------------------------------------------|------------|
| Java 方法 | Kotlin 函数 | 说明 |
| java<br>public int add(int a, int b) {<br> return a + b;<br>}<br> | kotlin<br>fun add(a: Int, b: Int): Int {<br> return a + b<br>}<br> | 基本函数 |
| java<br>void print(String msg) {<br> System.out.println(msg);<br>}<br> | kotlin<br>fun print(msg: String) {<br> println(msg)<br>}<br> | 无返回值 |
| java<br>String getName() {<br> return this.name;<br>}<br> | kotlin<br>val name: String<br> get() = field<br> | Getter方法 |

五、类与继承对照

1. 类定义

java 复制代码
// Java

public class Person {
    private String name;
    private int age;
    

    public Person(String name, int age) {

        this.name = name;
        this.age = age;
    }

    public void sayHello() {

        System.out.println("Hello, I'm " + name);

    }

}
Kotlin 复制代码
// Kotlin
class Person(val name: String, val age: Int) {

    fun sayHello() {

        println("Hello, I'm $name")

    }

}

2. 继承

java 复制代码
// Java
public class Student extends Person {
    private String studentId;

   
    public Student(String name, int age, String studentId) {
        super(name, age);
        this.studentId = studentId;
    }
}
Kotlin 复制代码
// Kotlin
open class Person(val name: String, val age: Int)

class Student(name: String, age: Int, val studentId: String)

    : Person(name, age)

六、接口与实现

java 复制代码
// Java
public interface Animal {
    void eat();
    void sleep();
}

public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("Dog is eating");

    }

    

    @Override
    public void sleep() {
        System.out.println("Dog is sleeping");

    }

}
Kotlin 复制代码
// Kotlin
interface Animal {
    fun eat()
    fun sleep()

}

class Dog : Animal {
    override fun eat() {

        println("Dog is eating")

    }

    

    override fun sleep() {
        println("Dog is sleeping")

    }

}

七、集合操作对照

|--------------------------------------------|--------------------------------------|------------|
| Java 操作 | Kotlin 操作 | 说明 |
| List<String> list = new ArrayList<>(); | val list = mutableListOf<String>() | 创建可变列表 |
| list.add("item"); | list.add("item") | 添加元素 |
| list.get(0); | list[0] | 获取元素 |
| for (String item : list) {...} | for (item in list) {...} | 遍历 |
| list.stream().filter(...) | list.filter {...} | 过滤 |

八、空安全对照

java 复制代码
// Java (可能NPE)

String str = getString();

if (str != null) {
    int length = str.length();

}
Kotlin 复制代码
// Kotlin (空安全)
val str: String? = getString()
val length = str?.length  // 安全调用

// 或使用 Elvis 操作符
val length = str?.length ?: 0

// 非空断言(谨慎使用)
val length = str!!.length

九、扩展函数(Kotlin特有)

Kotlin 复制代码
// Kotlin 扩展函数(Java中没有对应功能)
fun String.addExclamation(): String {
    return "$this!"
}

// 使用
val greeting = "Hello".addExclamation()  // "Hello!"

十、数据类(Kotlin特有)

Kotlin 复制代码
// Kotlin 数据类(替代Java的POJO)
data class User(
    val id: Long,
    val name: String,
    val email: String
)

// 自动生成:equals(), hashCode(), toString(), copy(), componentN()

十一、单例模式对照

Kotlin 复制代码
// Java 单例
public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
Kotlin 复制代码
// Kotlin 单例(使用object关键字)
object Singleton {
    fun doSomething() {
        println("Singleton operation")
    }
}

// 使用
Singleton.doSomething()

十二、实用转换技巧

1. 类型转换

Kotlin 复制代码
// Java
Object obj = "123";
if (obj instanceof String) {
    String str = (String) obj;
    int num = Integer.parseInt(str);
}
Kotlin 复制代码
// Kotlin
val obj: Any = "123"
if (obj is String) {
    val num = obj.toInt()  // 智能转换
}

2. 字符串模板

java 复制代码
// Java
String message = "Hello, " + name + "! You are " + age + " years old.";
Kotlin 复制代码
// Kotlin
val message = "Hello, $name! You are $age years old."

Java 转 Kotlin 详细语法对照表

一、基础语法对照

1. 变量与常量

|--------------------------------------|---------------------------|------------|
| Java | Kotlin | 说明 |
| int x = 5; | val x: Int = 5 | 不可变变量 |
| int y; y = 10; | var y: Int = 10 | 可变变量 |
| final int MAX = 100; | const val MAX = 100 | 编译时常量 |
| static final String NAME = "Kotlin"; | const val NAME = "Kotlin" | 静态常量 |

Kotlin 复制代码
// 类型推断
val name = "Kotlin"  // 自动推断为String
var count = 0        // 自动推断为Int

// 延迟初始化
lateinit var service: MyService
val lazyValue: String by lazy {
    "Computed only once"
}

2. 空安全处理

|------------------------------------|-------------------------|------------|
| Java | Kotlin | 说明 |
| String str = null; | val str: String? = null | 可空类型 |
| if (str != null) { str.length(); } | str?.length | 安全调用 |
| str != null ? str : "default" | str ?: "default" | Elvis操作符 |
| Objects.requireNonNull(str) | str!! | 非空断言 |

Kotlin 复制代码
// 安全调用链
val length = user?.address?.city?.length

// Elvis操作符
val name = nullableName ?: "Unknown"

// 安全转换
val number: Int? = str as? Int

二、控制结构对照

1. 条件表达式

|----------------------------------------------|-----------------------------|------------|
| Java | Kotlin | 说明 |
| if (a > b) { return a; } else { return b; } | return if (a > b) a else b | if表达式 |
| switch (x) { case 1: ... } | when (x) { 1 -> ... } | when表达式 |

Kotlin 复制代码
// when表达式
val description = when (x) {
    1 -> "One"
    2, 3 -> "Two or Three"
    in 4..10 -> "Between 4 and 10"
    else -> "Other"
}

// when作为表达式
val result = when {
    x > 0 -> "Positive"
    x < 0 -> "Negative"
    else -> "Zero"
}

2. 循环结构

|------------------------------|------------------------------|------------|
| Java | Kotlin | 说明 |
| for (int i=0; i<10; i++) | for (i in 0 until 10) | 范围循环 |
| for (String item : list) | for (item in list) | 集合遍历 |
| while (condition) { ... } | while (condition) { ... } | while循环 |
| do { ... } while (condition) | do { ... } while (condition) | do-while循环 |

Kotlin 复制代码
// 带索引遍历
for ((index, value) in list.withIndex()) {
    println("$index: $value")
}

// 步长循环
for (i in 10 downTo 1 step 2) {
    println(i) // 10, 8, 6, 4, 2
}

// 遍历map
for ((key, value) in map) {
    println("$key = $value")
}

三、函数/方法对照

1. 函数定义

|-------------------------------------------|---------------------------------------------------|------------|
| Java | Kotlin | 说明 |
| int add(int a, int b) { return a+b; } | fun add(a: Int, b: Int): Int = a + b | 单表达式函数 |
| void print(String msg) { ... } | fun print(msg: String): Unit { ... } | Unit返回类型 |
| String format(String fmt, Object... args) | fun format(fmt: String, vararg args: Any): String | 可变参数 |

Kotlin 复制代码
// 默认参数
fun greet(name: String = "Guest") {
    println("Hello, $name")
}

// 命名参数
greet(name = "Alice")

// 扩展函数
fun String.addExclamation(): String = "$this!"

// 中缀函数
infix fun Int.times(str: String) = str.repeat(this)
val result = 3 times "Hi"  // "HiHiHi"

2. 高阶函数与Lambda

|-------------------------------------|----------------------|------------|
| Java | Kotlin | 说明 |
| interface Callback { void call(); } | () -> Unit | 函数类型 |
| list.stream().map(x -> x*2) | list.map { it * 2 } | Lambda表达式 |

Kotlin 复制代码
// 函数类型
val sum: (Int, Int) -> Int = { a, b -> a + b }

// 带接收者的Lambda
val stringBuilder = StringBuilder().apply {
    append("Hello")
    append(" ")
    append("World")
}

// 内联函数
inline fun measureTime(block: () -> Unit) {
    val start = System.currentTimeMillis()
    block()
    val end = System.currentTimeMillis()
    println("Time: ${end - start}ms")
}

四、类与对象对照

1. 类定义

|----------------------------------------------|----------------------------------------|------------|
| Java | Kotlin | 说明 |
| public class Person { private String name; } | class Person(private val name: String) | 主构造函数 |
| new Person("Alice") | Person("Alice") | 对象创建 |
| this.name = name; | init { this.name = name } | 初始化块 |

Kotlin 复制代码
// 主构造函数
class Person(val name: String, var age: Int) {
    init {
        require(age >= 0) { "Age cannot be negative" }
    }
    
    // 次构造函数
    constructor(name: String) : this(name, 0)
}

// 数据类(自动生成equals/hashCode/toString/copy)
data class User(val id: Long, val name: String, val email: String)

// 密封类
sealed class Result {
    data class Success(val data: Any) : Result()
    data class Error(val message: String) : Result()
}

2. 继承与接口

|---------------------------------|-------------------------------|------------|
| Java | Kotlin | 说明 |
| class Child extends Parent | class Child : Parent() | 继承 |
| class A implements B, C | class A : B, C | 实现接口 |
| @Override void method() { ... } | override fun method() { ... } | 重写方法 |

Kotlin 复制代码
// 抽象类
abstract class Shape {
    abstract fun area(): Double
    open fun draw() { println("Drawing shape") }
}

// 继承
class Circle(val radius: Double) : Shape() {
    override fun area() = Math.PI * radius * radius
    final override fun draw() { println("Drawing circle") }
}

// 接口默认实现
interface Clickable {
    fun click()
    fun showOff() = println("I'm clickable!")
}

五、属性与访问器

|----------------------------------------------------------------------------------------------------------------------|-----------------------|---------------------|
| Java | Kotlin | 说明 |
| private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } | var name: String = "" | 属性自动生成getter/setter |
| private final int id; public int getId() { return id; } | val id: Int | 只读属性 |

Kotlin 复制代码
// 自定义getter/setter
class Rectangle(val width: Int, val height: Int) {
    val area: Int
        get() = width * height
        
    var borderColor: String = "black"
        set(value) {
            field = if (value.isNotEmpty()) value else "black"
        }
}

// 幕后字段
var counter = 0
    set(value) {
        if (value >= 0) field = value
    }

六、集合操作对照

1. 集合创建

|-------------------------------------------------|-----------------------------------------|------------|
| Java | Kotlin | 说明 |
| List<String> list = new ArrayList<>(); | val list = mutableListOf<String>() | 可变列表 |
| Set<Integer> set = new HashSet<>(); | val set = mutableSetOf<Int>() | 可变集合 |
| Map<String, Integer> map = new HashMap<>(); | val map = mutableMapOf<String, Int>() | 可变映射 |

Kotlin 复制代码
// 只读集合
val readOnlyList = listOf(1, 2, 3)
val readOnlySet = setOf("A", "B", "C")
val readOnlyMap

2. 集合操作

|--------------------|-----------------------------------|------------|
| Java | Kotlin | 说明 |
| list.add("item") | list.add("item") 或 list += "item" | 添加元素 |
| list.get(0) | list[0] | 获取元素 |
| list.set(0, "new") | list[0] = "new" | 设置元素 |
| list.size() | list.size | 集合大小 |
| list.isEmpty() | list.isEmpty() | 判空 |

Kotlin 复制代码
// 集合操作符
val numbers = listOf(1, 2, 3, 4, 5)

// 过滤
val evens = numbers.filter { it % 2 == 0 }  // [2, 4]

// 映射
val squares = numbers.map { it * it }  // [1, 4, 9, 16, 25]

// 查找
val firstEven = numbers.find { it % 2 == 0 }  // 2

// 分组
val grouped = numbers.groupBy { if (it % 2 == 0) "even" else "odd" }

// 排序
val sorted = numbers.sorted()
val sortedDesc = numbers.sortedDescending()

// 聚合
val sum = numbers.sum()  // 15
val max = numbers.maxOrNull()  // 5
val avg = numbers.average()  // 3.0

3. 序列(Stream替代)

|-------------------------------|--------------------------------|------------|
| Java Stream | Kotlin Sequence | 说明 |
| list.stream().filter(...) | list.asSequence().filter {...} | 惰性求值 |
| .map(...) | .map {...} | 转换 |
| .collect(Collectors.toList()) | .toList() | 收集结果 |
| .limit(10) | .take(10) | 限制数量 |
| .skip(5) | .drop(5) | 跳过元素 |

Kotlin 复制代码
// 序列操作(惰性求值)
val result = (1..1_000_000)
    .asSequence()
    .filter { it % 2 == 0 }
    .map { it * 2 }
    .take(10)
    .toList()

七、异常处理对照

|-----------------------------------------|------------------------------------------|---------------|
| Java | Kotlin | 说明 |
| try { ... } catch (Exception e) { ... } | try { ... } catch (e: Exception) { ... } | 基本try-catch |
| try { ... } finally { ... } | try { ... } finally { ... } | finally块 |
| throw new Exception("error") | throw Exception("error") | 抛出异常 |
| throws IOException | 不需要声明 | Kotlin不强制检查异常 |

Kotlin 复制代码
// try-catch表达式
val number = try {
    "123".toInt()
} catch (e: NumberFormatException) {
    0
}

// 使用runCatching
val result = runCatching {
    "abc".toInt()
}.getOrElse { 
    0 
}

// 多个catch块
try {
    // 可能抛出异常的代码
} catch (e: IOException) {
    println("IO错误: ${e.message}")
} catch (e: IllegalArgumentException) {
    println("参数错误: ${e.message}")
} finally {
    println("清理资源")
}

八、泛型对照

|---------------------------|-------------------------------|------------|
| Java | Kotlin | 说明 |
| List<String> | List<String> | 泛型类型 |
| T method(T param) | fun <T> method(param: T): T | 泛型方法 |
| class Box<T> | class Box<T> | 泛型类 |
| ? extends Number | out Number | 协变 |
| ? super Number | in Number | 逆变 |
| T extends Comparable<T> | T : Comparable<T> | 类型约束 |

Kotlin 复制代码
// 泛型函数
fun <T> singletonList(item: T): List<T> = listOf(item)

// 泛型类
class Box<T>(val value: T)

// 类型约束
fun <T : Comparable<T>> sort(list: List<T>): List<T> = list.sorted()

// 多个约束
fun <T> cloneIfGreater(list: List<T>, threshold: T): List<T>
    where T : Comparable<T>, T : Cloneable {
    return list.filter { it > threshold }
}

// 星投影(相当于Java的?)
fun printList(list: List<*>) {
    for (item in list) {
        println(item)
    }
}

九、注解与反射

|--------------------------------|-----------------------------|------------|
| Java | Kotlin | 说明 |
| @Override | override(关键字) | 重写方法 |
| @Deprecated | @Deprecated | 废弃标记 |
| @SuppressWarnings("unchecked") | @Suppress("UNCHECKED_CAST") | 抑制警告 |
| @Nullable | ?(可空类型) | 空值标记 |
| @NotNull | 非空类型(默认) | 非空标记 |

Kotlin 复制代码
// 自定义注解
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Fancy(val name: String)

// 使用注解
@Fancy("MyClass")
class MyClass {
    @Fancy("myMethod")
    fun myMethod() {}
}

// Java注解在Kotlin中使用
@JvmStatic
@JvmOverloads
@Throws(IOException::class)
fun javaInteropMethod() { }

// 反射
val kClass = MyClass::class
val properties = kClass.memberProperties
val functions = kClass.memberFunctions

十、作用域函数(Kotlin特有)

|------------|---------------|-------------|--------------|
| 函数 | 上下文对象 | 返回值 | 使用场景 |
| let | it | Lambda结果 | 非空对象处理 |
| run | this | Lambda结果 | 对象配置和计算 |
| with | this | Lambda结果 | 调用对象方法 |
| apply | this | 对象本身 | 对象初始化 |
| also | it | 对象本身 | 附加操作 |

Kotlin 复制代码
// let - 处理可空对象
val length = nullableString?.let { 
    println("Processing: $it")
    it.length 
} ?: 0

// run - 对象配置和计算
val result = service.run {
    port = 8080
    start()
    query()
}

// with - 调用对象方法
with(window) {
    width = 800
    height = 600
    isVisible = true
}

// apply - 对象初始化
val person = Person().apply {
    name = "Alice"
    age = 25
    address = "New York"
}

// also - 附加操作
val numbers = mutableListOf(1, 2, 3)
    .also { println("List created: $it") }
    .apply { add(4) }
    .also { println("After adding 4: $it") }

十一、协程(替代Java线程)

|----------------------------------|-------------------------------------|------------|
| Java 线程 | Kotlin 协程 | 说明 |
| new Thread(() -> {...}).start() | launch { ... } | 启动协程 |
| ExecutorService | CoroutineScope | 协程作用域 |
| Future<T> | Deferred<T> | 异步结果 |
| Thread.sleep(1000) | delay(1000) | 非阻塞延迟 |
| synchronized(obj) {...} | withContext(Dispatchers.Main) {...} | 线程切换 |

Kotlin 复制代码
// 基本协程
GlobalScope.launch {
    delay(1000L)  // 非阻塞延迟
    println("World!")
}
println("Hello,")

// 异步操作
suspend fun fetchUser(): User {
    return withContext(Dispatchers.IO) {
        // 网络请求
        api.getUser()
    }
}

// 并发执行
val user = async { fetchUser() }
val posts = async { fetchPosts() }
println("User: ${user.await()}, Posts: ${posts.await()}")

// 结构化并发
coroutineScope {
    launch {
        delay(200L)
        println("Task from nested launch")
    }
    delay(100L)
    println("Task from coroutine scope")
}

// 取消协程
val job = launch {
    repeat(1000) { i ->
        println("job: I'm sleeping $i ...")
        delay(500L)
    }
}
delay(1300L)
job.cancel()

十二、DSL构建器

Kotlin 复制代码
// HTML DSL示例
fun

十二、DSL构建器(Kotlin特有)

|-------------------------------------------------------------|---------------------------------|------------|
| Java Builder模式 | Kotlin DSL | 说明 |
| new AlertDialog.Builder(context).setTitle("Title").create() | alertDialog { title = "Title" } | DSL构建器 |
| XML/JSON配置 | 类型安全的DSL | 配置构建 |

Kotlin 复制代码
// HTML DSL示例
fun createHTML(): String = html {
    head {
        title { +"Kotlin DSL" }
    }
    body {
        h1 { +"Welcome" }
        p {
            +"This is Kotlin DSL"
        }
    }
}

// 自定义DSL
class DatabaseConfig {
    var url: String = ""
    var username: String = ""
    var password: String = ""
    
    fun build() = "jdbc:$url?user=$username&password=$password"
}

fun database(block: DatabaseConfig.() -> Unit): String {
    val config = DatabaseConfig()
    config.block()
    return config.build()
}

// 使用
val connection = database {
    url = "mysql://localhost:3306/mydb"
    username = "admin"
    password = "secret"
}

十三、委托(Kotlin特有)

|----------------|------------------|------------|
| Java模式 | Kotlin委托 | 说明 |
| 装饰器模式 | 类委托 | 实现继承的替代 |
| 观察者模式 | 属性委托 | 属性变化监听 |
| 懒加载模式 | lazy委托 | 延迟初始化 |

Kotlin 复制代码
// 类委托
interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { println(x) }
}

class Derived(b: Base) : Base by b  // 将b的方法委托给Derived

// 属性委托
class Delegate {
    private var value: String = ""
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        println("Getting value: $value")
        return value
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("Setting value: $value")
        this.value = value
    }
}

class Example {
    var p: String by Delegate()
}

// 使用
val e = Example()
e.p = "Hello"  // 输出: Setting value: Hello
println(e.p)    // 输出: Getting value: Hello 然后输出: Hello

// 标准库委托
class User {
    val lazyValue: String by lazy {
        println("computed!")
        "Hello"
    }
    
    var observableValue: String by Delegates.observable("初始值") { 
        prop, old, new ->
        println("$old -> $new")
    }
    
    var vetoableValue: Int by Delegates.vetoable(0) { 
        prop, old, new ->
        new >= 0  // 只有新值>=0时才更新
    }
}

十四、类型检查与转换

|--------------------------------------------------------|--------------------------------------------|------------|
| Java | Kotlin | 说明 |
| obj instanceof String | obj is String | 类型检查 |
| (String) obj | obj as String | 强制转换 |
| if (obj instanceof String) { String s = (String)obj; } | if (obj is String) { println(obj.length) } | 智能转换 |
| Class<?> clazz = obj.getClass() | val clazz = obj::class | 获取类对象 |

Kotlin 复制代码
// 类型检查与转换
val obj: Any = "Hello"

// 安全转换
val str1: String? = obj as? String  // 转换失败返回null

// 强制转换
val str2: String = obj as String  // 转换失败抛出异常

// 智能转换
if (obj is String) {
    println(obj.length)  // obj自动转换为String
}

// when表达式中的智能转换
when (obj) {
    is String -> println(obj.length)
    is Int -> println(obj + 1)
    is List<*> -> println(obj.size)
}

// 泛型类型检查
fun <T> checkType(value: Any): T? {
    return if (value is T) value else null  // 注意:这里不能工作,因为T被擦除了
}

// 使用内联函数和reified类型参数
inline fun <reified T> checkTypeReified(value: Any): T? {
    return if (value is T) value else null
}

val result: String? = checkTypeReified("Hello")  // 可以工作

十五、伴生对象与静态成员

|------------------------------|-------------------------------------------|------------|
| Java静态成员 | Kotlin对应 | 说明 |
| static final int MAX = 100; | const val MAX = 100 | 编译时常量 |
| static int count = 0; | companion object { var count = 0 } | 伴生对象属性 |
| static void method() { ... } | companion object { fun method() { ... } } | 伴生对象方法 |
| MyClass.class | MyClass::class | 类字面量 |

Kotlin 复制代码
class MyClass {
    companion object {
        const val VERSION = "1.0"
        
        var instanceCount = 0
        
        fun create(): MyClass {
            instanceCount++
            return MyClass()
        }
        
        @JvmStatic  // 让Java可以像调用静态方法一样调用
        fun staticMethod() {
            println("This is a static-like method")
        }
    }
    
    init {
        instanceCount++
    }
}

// 使用
println(MyClass.VERSION)  // 1.0
val obj = MyClass.create()
println(MyClass.instanceCount)  // 2

// 伴生对象可以有名字
class MyClass2 {
    companion object Factory {
        fun create(): MyClass2 = MyClass2()
    }
}

// 实现接口的伴生对象
interface Factory<T> {
    fun create(): T
}

class MyClass3 {
    companion object : Factory<MyClass3> {
        override fun create(): MyClass3 = MyClass3()
    }
}

十六、内联类(值类)

|----------------------------------------------------|----------------------------------------------------|------------|
| Java包装类 | Kotlin内联类 | 说明 |
| public class Email { private final String value; } | inline class Email(val value: String) | 类型安全的包装 |
| Integer.valueOf(42) | @JvmInline value class Password(val value: String) | 运行时无开销 |

Kotlin 复制代码
// 内联类(Kotlin 1.3+)
@JvmInline
value class Password(val value: String) {
    init {
        require(value.length >= 8) { "密码至少8位" }
    }
    
    fun isStrong(): Boolean = value.any { it.isDigit() } 
        && value.any { it.isLetter() }
}

// 使用
fun authenticate(password: Password) {
    println("验证密码: ${password.value}")
    println("强度: ${if (password.isStrong()) "强" else "弱"}")
}

val myPassword = Password("Secure123")
authenticate(myPassword)

// 多个内联类
@JvmInline
value class UserId(val id: Long)

@JvmInline
value class ProductId(val id: Long)

fun getUser(id: UserId) { /* ... */ }
fun getProduct(id: ProductId) { /* ... */ }

// 编译时类型安全,运行时无开销
val userId = UserId(123L)
val productId = ProductId(456L)
getUser(userId)      // OK
getUser(productId)   // 编译错误:类型不匹配

十七、解构声明

|----------------|------------------|------------|
| Java解构 | Kotlin解构 | 说明 |
| 需要手动提取 | 自动解构 | 从对象中提取多个值 |

Kotlin 复制代码
// 数据类的解构
data class Person(val name: String, val age: Int, val city: String)

val person = Person("Alice", 25, "New York")

// 解构声明
val (name, age, city) = person
println("$name is $age years old from $city")

// 忽略某些组件
val (_, ageOnly, _) = person
println("Age: $ageOnly")

// Map的解构
val map = mapOf("name" to "Bob", "age" to 30)
for ((key, value) in map) {
    println("$key = $value")
}

// 函数返回多个值
data class Result(val success: Boolean, val message: String)

fun process(): Result {
    return Result(true, "操作成功")
}

val (success, message) = process()
if (success) {
    println(message)
}

// 自定义解构
class Point(val x: Int, val y: Int) {
    operator fun component1() = x
    operator fun component2() = y
}

val point = Point(10, 20)
val (x, y) = point

十八、操作符重载

|------------------|---------------------|------------|
| Java 操作符 | Kotlin 对应 | 说明 |
| a + b | a.plus(b) | 加法 |
| a - b | a.minus(b) | 减法 |
| a * b | a.times(b) | 乘法 |
| a / b | a.div(b) | 除法 |
| a % b | a.rem(b) | 取余 |
| a++ | a.inc() | 自增 |
| a-- | a.dec() | 自减 |
| a == b | a.equals(b) | 相等 |
| a > b | a.compareTo(b) > 0 | 比较 |
| a[i] | a.get(i) | 索引访问 |
| a[i] = b | a.set(i, b) | 索引赋值 |

Kotlin 复制代码
// 自定义操作符重载
data class Point(val x: Int, val y: Int) {
    // 重载 + 运算符
    operator fun plus(other: Point): Point {
        return Point(x + other.x, y + other.y)
    }
    
    // 重载 - 运算符
    operator fun minus(other: Point): Point {
        return Point(x - other.x, y - other.y)
    }
    
    // 重载 * 运算符
    operator fun times(factor: Int): Point {
        return Point(x * factor, y * factor)
    }
    
    // 重载 == 运算符(数据类自动生成)
    
    // 重载比较运算符
    operator fun compareTo(other: Point): Int {
        return (x + y).compareTo(other.x + other.y)
    }
    
    // 重载一元运算符
    operator fun unaryMinus(): Point {
        return Point(-x, -y)
    }
}

// 使用
val p1 = Point(1, 2)
val p2 = Point(3, 4)

val p3 = p1 + p2  // Point(4, 6)
val p4 = p2 - p1  // Point(2, 2)
val p5 = p1 * 3   // Point(3, 6)
val p6 = -p1      // Point(-1, -2)

if (p1 < p2) {
    println("p1 is less than p2")
}

// 索引访问操作符重载
class Matrix(val rows: Int, val cols: Int) {
    private val data = Array(rows) { DoubleArray(cols) }
    
    operator fun get(row: Int, col: Int): Double {
        return data[row][col]
    }
    
    operator fun set(row: Int, col: Int, value: Double) {
        data[row][col] = value
    }
}

val matrix = Matrix(3, 3)
matrix[0, 0] = 1.0
println(matrix[0, 0])  // 1.0

// 调用操作符重载
class Greeter(val prefix: String) {
    operator fun invoke(name: String) {
        println("$prefix, $name!")
    }
}

val hello = Greeter("Hello")
hello("World")  // 输出: Hello, World!

十九、中缀函数

|-------------------|---------------------|------------|
| Java 方法调用 | Kotlin 中缀调用 | 说明 |
| obj.method(arg) | obj method arg | 中缀表示法 |

Kotlin 复制代码
// 定义中缀函数
infix fun Int.add(other: Int): Int = this + other

infix fun String.should(startWith: String): Boolean {
    return this.startsWith(startWith)
}

// 使用中缀函数
val result = 5 add 3  // 等价于 5.add(3)
println(result)  // 8

val isValid = "Hello" should "He"
println(isValid)  // true

// 自定义中缀函数用于DSL
class Database {
    infix fun select(columns: String): QueryBuilder {
        return QueryBuilder(this, columns)
    }
}

class QueryBuilder(val db: Database, val columns: String) {
    infix fun from(table: String): QueryBuilder {
        println("SELECT $columns FROM $table")
        return this
    }
    
    infix fun where(condition: String): QueryBuilder {
        println("WHERE $condition")
        return this
    }
}

// 创建DSL风格的查询
val db = Database()
db select "*" from "users" where "age > 18"

// 范围中缀函数
val range = 1..10  // 使用中缀表示法
val range2 = 1.rangeTo(10)  // 等价写法

val rangeUntil = 1 until 10  // 1..9
val charRange = 'a'..'z'

// 检查包含关系
if (5 in 1..10) {
    println("5在1到10之间")
}

二十、类型别名

|----------------------------------------------|----------------------------------------------------------------|------------|
| Java 冗长类型 | Kotlin 类型别名 | 说明 |
| Map<String, List<Map<String, Object>>> | typealias UserData = Map<String, List<Map<String, Any>>> | 简化复杂类型 |

Kotlin 复制代码
// 类型别名
typealias UserId = String
typealias UserMap = Map<UserId, User>
typealias ClickHandler = (View) -> Unit
typealias Predicate<T> = (T) -> Boolean

// 使用类型别名
data class User(val id: UserId, val name: String)

fun processUsers(users: UserMap) {
    for ((id, user) in users) {
        println("User $id: ${user.name}")
    }
}

// 函数类型别名
typealias StringFilter = (String) -> Boolean

fun filterStrings(strings: List<String>, filter: StringFilter): List<String> {
    return strings.filter(filter)
}

val strings = listOf("apple", "banana", "cherry")
val longStrings = filterStrings(strings) { it.length > 5 }

// 泛型类型别名
typealias StringMap<V> = Map<String, V>
typealias ListOrSet<T> = List<T> or Set<T>  // Kotlin 1.6+ 支持

// 类类型别名
typealias FileTable = MutableMap<Int, MutableList<File>>

// 内部类类型别名
class Outer {
    inner class Inner
}
typealias OuterInner = Outer.Inner

// 与扩展函数结合
typealias IntPredicate = (Int) -> Boolean

fun Int.isEven(): Boolean = this % 2 == 0

val isEven: IntPredicate = Int::isEven
println(isEven(4))  // true

二十一、密封类与枚举增强

|---------------------|---------------------|------------|
| Java枚举/模式匹配 | Kotlin密封类 | 说明 |
| enum + switch | sealed class + when | 更强大的枚举 |
| Visitor模式 | 密封类层次结构 | 类型安全的模式匹配 |

Kotlin 复制代码
// 密封类(受限的类层次结构)
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

// 使用when表达式(完全覆盖所有情况)
fun handleResult(result: Result<String>) {
    when (result) {
        is Result.Success -> println("成功: ${result.data}")
        is Result.Error -> println("错误: ${result.exception.message}")
        Result.Loading -> println("加载中...")
        // 不需要else分支,因为所有情况都已覆盖
    }
}

// 更复杂的密封类层次
sealed class Expression {
    data class Number(val value: Int) : Expression()
    data class Sum(val left: Expression, val right: Expression) : Expression()
    data class Multiply(val left: Expression, val right: Expression) : Expression()
}

fun evaluate(expr: Expression): Int = when (expr) {
    is Expression.Number -> expr.value
    is Expression.Sum -> evaluate(expr.left) + evaluate(expr.right)
    is Expression.Multiply -> evaluate(expr.left) * evaluate(expr.right)
}

// 枚举类增强
enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF);
    
    fun containsRed(): Boolean = (this.rgb and 0xFF0000 != 0)
}

// 枚举与when结合
fun getColorDescription(color: Color): String = when (color) {
    Color.RED -> "热情的颜色"
    Color.GREEN -> "自然的颜色"
    Color.BLUE -> "冷静的颜色"
}

// 密封类与枚举的区别
sealed class PaymentMethod
data class CreditCard(val number: String, val expiry: String) : PaymentMethod()
data class PayPal(val email: String) : PaymentMethod()
object Cash : PaymentMethod()

// 枚举适用于固定值,密封类适用于有数据的变体
enum

二十二、内联函数与具体化类型参数

|-------------------|---------------------|------------|
| Java 泛型限制 | Kotlin 解决方案 | 说明 |
| 类型擦除 | reified 类型参数 | 运行时保留类型信息 |
| 高阶函数性能开销 | inline 函数 | 消除函数调用开销 |

Kotlin 复制代码
// 内联函数消除lambda开销
inline fun <T> measureTimeMillis(block: () -> T): T {
    val start = System.currentTimeMillis()
    val result = block()
    val end = System.currentTimeMillis()
    println("Execution time: ${end - start}ms")
    return result
}

// 使用
val result = measureTimeMillis {
    // 耗时操作
    (1..1000000).sum()
}

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

inline fun <reified T> List<*>.filterIsInstance(): List<T> {
    return filter { it is T }.map { it as T }
}

// 使用
val list: List<Any> = listOf(1, "hello", 2, "world")
val strings: List<String> = list.filterIsInstance<String>()  // ["hello", "world"]
val numbers: List<Int> = list.filterIsInstance<Int>()        // [1, 2]

// 内联属性
inline val <T> List<T>.lastIndex: Int
    get() = size - 1

// noinline 和 crossinline
inline fun doSomething(
    crossinline onSuccess: () -> Unit,
    noinline onError: (Exception) -> Unit
) {
    try {
        // ...
        onSuccess()
    } catch (e: Exception) {
        onError(e)
    }
}

二十三、委托属性进阶

Kotlin 复制代码
// 自定义属性委托
class RangeDelegate(
    private val start: Int,
    private val endInclusive: Int
) {
    private var value: Int = start
    
    operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        println("Getting value: $value")
        return value
    }
    
    operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: Int) {
        println("Setting value: $newValue")
        require(newValue in start..endInclusive) {
            "Value must be between $start and $endInclusive"
        }
        value = newValue
    }
}

class Person {
    var age: Int by RangeDelegate(0, 150)
    var score: Int by RangeDelegate(0, 100)
}

// 使用
val person = Person()
person.age = 25  // OK
person.age = 200 // 抛出异常

// Map委托
class Config(properties: Map<String, Any>) {
    val host: String by properties
    val port: Int by properties
    val debug: Boolean by properties
}

val config = Config(mapOf(
    "host" to "localhost",
    "port" to 8080,
    "debug" to true
))

// 提供者委托
fun <T> provideDelegate(
    thisRef: Any?,
    property: KProperty<*>
): ReadOnlyProperty<Any?, T> {
    // 可以在这里进行验证或初始化
    println("Initializing ${property.name}")
    return object : ReadOnlyProperty<Any?, T> {
        override fun getValue(thisRef: Any?, property: KProperty<*>): T {
            // 返回默认值或计算值
            return "Default" as T
        }
    }
}

二十四、多平台项目(Kotlin Multiplatform)

|--------------------|------------------------------|------------|
| Java 跨平台方案 | Kotlin Multiplatform | 说明 |
| 共享JAR库 | 共享Kotlin代码 | 真正的代码共享 |
| 平台特定实现 | expect/actual | 声明期望和实际实现 |

Kotlin 复制代码
// 公共模块 - commonMain
expect class Platform() {
    val platform: String
}

expect fun currentTimeMillis(): Long

class Greeting {
    fun greet(): String {
        return "Hello from ${Platform().platform} at ${currentTimeMillis()}"
    }
}

// Android实现 - androidMain
actual class Platform actual constructor() {
    actual val platform: String = "Android"
}

actual fun currentTimeMillis(): Long = System.currentTimeMillis()

// iOS实现 - iosMain
import platform.Foundation.NSDate
import platform.Foundation.timeIntervalSince1970

actual class Platform actual constructor() {
    actual val platform: String = "iOS"
}

actual fun currentTimeMillis(): Long = 
    (NSDate().timeIntervalSince1970 * 1000).toLong()

// JVM实现 - jvmMain
actual class Platform actual constructor() {
    actual val platform: String = "JVM"
}

actual fun currentTimeMillis(): Long = System.currentTimeMillis()

二十五、协程流(Flow)

|-------------------|---------------------|------------|
| Java 响应式流 | Kotlin Flow | 说明 |
| RxJava/Observable | Flow | 冷流,更轻量 |
| Stream | Flow | 异步数据流 |

Kotlin 复制代码
// 创建Flow
fun simpleFlow(): Flow<Int> = flow {
    for (i in 1..3) {
        delay(100) // 模拟异步操作
        emit(i)    // 发射值
    }
}

// 收集Flow
fun main() = runBlocking {
    simpleFlow()
        .map { it * it }          // 转换
        .filter { it % 2 != 0 }   // 过滤
        .collect { value ->       // 收集
            println(value)
        }
}

// 状态流
val stateFlow = MutableStateFlow(0)

// 共享流
val sharedFlow = MutableSharedFlow<Int>()

// Flow操作符
fun processFlow(): Flow<String> = flow {
    emit("Apple")
    emit("Banana")
    emit("Cherry")
}

fun main() = runBlocking {
    processFlow()
        .onEach { println("Processing: $it") }
        .map { it.uppercase() }
        .catch { e -> emit("Error: ${e.message}") }
        .onCompletion { println("Completed") }
        .collect { println("Result: $it") }
}

// 与LiveData集成(Android)
fun <T> Flow<T>.asLiveData(): LiveData<T> = liveData {
    collect { value ->
        emit(value)
    }
}

二十六、上下文接收者(Context Receivers) - Kotlin 1.6.20+

Kotlin 复制代码
// 定义上下文
interface LoggingContext {
    val logger: Logger
}

interface DatabaseContext {
    val database: Database
}

// 上下文接收者函数
context(LoggingContext)
fun logInfo(message: String) {
    logger.info(message)
}

context(LoggingContext, DatabaseContext)
fun processUser(userId: String) {
    logInfo("Processing user: $userId")
    val user = database.findUser(userId)
    // 处理用户
}

// 提供上下文
class ApplicationContext : LoggingContext, DatabaseContext {
    override val logger = Logger.getLogger("App")
    override val database = Database.connect()
}

// 使用
fun main() {
    val context = ApplicationContext()
    
    with(context) {
        processUser("123")
    }
}

二十七、挂起函数与回调转换

|--------------------------|---------------------|------------|
| Java 回调模式 | Kotlin 挂起函数 | 说明 |
| 回调地狱 | 顺序代码 | 异步代码同步写 |
| Future/CompletableFuture | suspend函数 | 更简洁的异步 |

Kotlin 复制代码
// 将回调转换为挂起函数
suspend fun fetchUser(userId: String): User = suspendCoroutine { continuation ->
    api.getUser(userId, object : Callback<User> {
        override fun onSuccess(user: User) {
            continuation.resume(user)
        }
        
        override fun onError(error: Throwable) {
            continuation.resumeWithException(error)
        }
    })
}

// 使用回调转换器
fun <T> Callback<T>.asSuspend(): suspend () -> T = suspendCoroutine { cont ->
    this.enqueue(object : Callback<T> {
        override fun onResponse(call: Call<T>, response: Response<T>) {
            if (response.isSuccessful) {
                cont.resume(response.body()!!)
            } else {
                cont.resumeWithException(HttpException(response))
            }
        }
        
        override fun onFailure(call: Call<T>, t: Throwable) {
            cont.resumeWithException(t)
        }
    })
}

// 顺序执行异步操作
suspend fun loadUserData(userId: String): UserData {
    // 顺序执行,但不会阻塞线程
    val user = fetchUser(userId)
    val posts = fetchPosts(userId)
    val friends = fetchFriends(userId)
    
    return UserData(user, posts, friends)
}

// 并发执行异步操作
suspend fun loadUserDataConcurrent(userId: String): UserData = coroutineScope {
    val userDeferred = async {

二十八、反射与元编程

|-----------------------------------|--------------------------|------------|
| Java 反射 | Kotlin 反射 | 说明 |
| Class<?> clazz = obj.getClass() | val kClass = obj::class | 获取KClass |
| clazz.getMethod("name") | kClass.functions | 获取函数 |
| clazz.getField("field") | kClass.memberProperties | 获取属性 |
| method.invoke(obj, args) | function.call(obj, args) | 调用函数 |

Kotlin 复制代码
// 基本反射
data class Person(val name: String, val age: Int)

fun reflectExample() {
    val person = Person("Alice", 25)
    
    // 获取KClass
    val kClass = person::class
    println("Class name: ${kClass.simpleName}")
    
    // 获取属性
    val properties = kClass.memberProperties
    for (property in properties) {
        println("Property: ${property.name} = ${property.get(person)}")
    }
    
    // 获取函数
    val functions = kClass.functions
    for (function in functions) {
        println("Function: ${function.name}")
    }
    
    // 调用函数
    val toStringMethod = kClass.functions.find { it.name == "toString" }
    val result = toStringMethod?.call(person)
    println("toString result: $result")
}

// 注解处理
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
annotation class JsonName(val name: String)

@Target(AnnotationTarget.PROPERTY)
annotation class JsonExclude

data class User(
    @JsonName("user_name")
    val name: String,
    
    @JsonExclude
    val password: String,
    
    val email: String
)

fun serialize(obj: Any): String {
    val kClass = obj::class
    val properties = kClass.memberProperties
    
    return properties
        .filter { property -> 
            property.findAnnotation<JsonExclude>() == null 
        }
        .joinToString(", ") { property ->
            val jsonName = property.findAnnotation<JsonName>()?.name ?: property.name
            val value = property.get(obj)
            "\"$jsonName\": \"$value\""
        }
        .let { "{ $it }" }
}

// 动态创建实例
fun createInstance(kClass: KClass<*>, vararg args: Any?): Any? {
    val constructor = kClass.constructors.firstOrNull()
    return constructor?.call(*args)
}

// 使用
val personClass = Person::class
val newPerson = createInstance(personClass, "Bob", 30) as Person

二十九、DSL构建器模式

Kotlin 复制代码
// HTML DSL构建器
interface Element {
    fun render(builder: StringBuilder, indent: String)
}

class TextElement(val text: String) : Element {
    override fun render(builder: StringBuilder, indent: String) {
        builder.append("$indent$text\n")
    }
}

class HtmlElement(val name: String) : Element {
    private val children = mutableListOf<Element>()
    private val attributes = mutableMapOf<String, String>()
    
    fun setAttribute(name: String, value: String) {
        attributes[name] = value
    }
    
    fun child(init: HtmlElement.() -> Unit) {
        val child = HtmlElement("div")
        child.init()
        children.add(child)
    }
    
    fun text(text: String) {
        children.add(TextElement(text))
    }
    
    override fun render(builder: StringBuilder, indent: String) {
        builder.append("$indent<$name")
        
        for ((attrName, attrValue) in attributes) {
            builder.append(" $attrName=\"$attrValue\"")
        }
        
        if (children.isEmpty()) {
            builder.append("/>\n")
        } else {
            builder.append(">\n")
            for (child in children) {
                child.render(builder, "$indent  ")
            }
            builder.append("$indent</$name>\n")
        }
    }
}

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

// 使用DSL
val page = html {
    setAttribute("lang", "en")
    
    child {
        name = "head"
        child {
            name = "title"
            text("My Page")
        }
    }
    
    child {
        name = "body"
        child {
            name = "h1"
            text("Welcome to Kotlin DSL")
        }
        child {
            name = "p"
            setAttribute("class", "content")
            text("This is a paragraph.")
        }
    }
}

// 数据库查询DSL
class QueryBuilder {
    private var select: String = "*"
    private var from: String = ""
    private var where: String = ""
    private var orderBy: String = ""
    
    fun select(columns: String) {
        select = columns
    }
    
    fun from(table: String) {
        from = table
    }
    
    fun where(condition: String) {
        where = "WHERE $condition"
    }
    
    fun orderBy(column: String) {
        orderBy = "ORDER BY $column"
    }
    
    fun build(): String {
        return "SELECT $select FROM $from $where $orderBy".trim()
    }
}

fun query(init: QueryBuilder.() -> Unit): String {
    val builder = QueryBuilder()
    builder.init()
    return builder.build()
}

// 使用
val sql = query {
    select("name, age")
    from("users")
    where("age > 18")
    orderBy("name")
}
// SELECT name, age FROM users WHERE age > 18 ORDER BY name

三十、Kotlin与Java互操作

1. 在Kotlin中调用Java代码

Kotlin 复制代码
// Java类
// public class JavaClass {
//     public static String staticMethod() { return "Hello"; }
//     public String instanceMethod() { return "World"; }
// }

// Kotlin调用
val staticResult = JavaClass.staticMethod()
val instance = JavaClass()
val instanceResult = instance.instanceMethod()

// 处理空安全
@Nullable
public String getNullableString() { return null; }

@NotNull  
public String getNotNullString() { return "not null"; }

// Kotlin中
val nullable: String? = javaClass.nullableString  // 可空类型
val notNull: String = javaClass.notNullString     // 非空类型

// SAM转换(单抽象方法接口)
// Java接口
// interface OnClickListener {
//     void onClick(View v);
// }

// Kotlin使用
view.setOnClickListener { v ->
    println("Clicked!")
}

// 使用Java流
val javaList = java.util.ArrayList<String>()
javaList.add("Java")
javaList.add("Kotlin")

val kotlinList = javaList.stream()
    .filter { it.startsWith("K") }
    .collect(Collectors.toList())

2. 在Java中调用Kotlin代码

java 复制代码
// Kotlin文件
@file:JvmName("KotlinUtils")  // 指定类名

object StringUtils {
    @JvmStatic  // 生成静态方法
    fun capitalize(str: String): String {
        return str.replaceFirstChar { it.uppercase() }
    }
    
    @JvmOverloads  // 生成重载方法
    fun join(separator: String = ", ", vararg parts: String): String {
        return parts.joinToString(separator)
    }
}

class User @JvmOverloads constructor(
    val name: String,
    val age: Int = 0,
    val email: String = ""
) {
    companion object {
        @JvmField  // 暴露为Java字段
        val DEFAULT_NAME = "Guest"
        
        @JvmStatic
        fun createDefault() = User(DEFAULT_NAME)
    }
}
java 复制代码
// Java中调用
// 调用顶层函数
String result = KotlinUtils.capitalize("hello");

// 调用带默认参数的函数
String joined1 = StringUtils.join(", ", "a", "b", "c");
String joined2 = StringUtils.join("a", "b", "c");  // 使用默认分隔符

// 创建对象
User user1 = new User("Alice", 25, "alice@example.com");
User user2 = new User("Bob");  // 使用默认参数

// 访问伴生对象
String defaultName = User.DEFAULT_NAME;
User defaultUser = User.createDefault();

三十一、性能优化技巧

1. 内联函数优化

Kotlin 复制代码
// 适合内联的情况
inline fun <T> synchronized(lock: Any, block: () -> T): T {
    synchronized(lock) {
        return block()
    }
}

// 不适合内联的情况(函数体大或递归)
fun processLargeData(data: List<Int>, processor: (Int) -> Int): List<Int> {
    return data.map(processor)  // 不要内联,因为map本身是内联的
}

2. 集合操作优化

Kotlin 复制代码
// 使用序列进行惰性求值(大数据集)
val largeList = (1..1_000_000).toList()

// 链式操作 - 创建多个中间集合
val result1 = largeList
    .filter { it % 2 == 0 }      // 创建中间集合1
    .map { it * 2 }              // 创建中间集合2  
    .take(1000)                  // 创建中间集合3
    .toList()

// 使用序列 - 无中间集合,惰性计算
val result2 = largeList.asSequence()
    .filter { it % 2 == 0 }      // 惰性过滤
    .map { it * 2 }              // 惰性映射
    .take(1000)                  // 只取前1000个
    .toList()                    // 最终结果

// 使用数组处理基本类型(避免装箱开销)
val intArray = IntArray(1000) { it }  // 基本类型int数组
val integerList = List(1000) { it }   // 装箱的Integer列表

// 性能对比
fun benchmark() {
    val size = 10_000_000
    
    // 使用List(装箱)
    val list = List(size) { it }
    val time1 = measureTimeMillis {
        val sum = list.sum()
    }
    
    // 使用IntArray(基本类型)
    val array = IntArray(size) { it }
    val time2 = measureTimeMillis {
        val sum = array.sum()
    }
    
    println("List time: $time1 ms")
    println("IntArray time: $time2 ms")
}

3. 字符串处理优化

Kotlin 复制代码
// 避免在循环中使用字符串连接
fun slowConcat(list: List<String>): String {
    var result = ""
    for (item in list) {
        result += item  // 每次创建新字符串对象
    }
    return result
}

fun fastConcat(list: List<String>): String {
    return StringBuilder().apply {
        for (item in list) {
            append(item)  // 使用StringBuilder
        }
    }.toString()
}

fun fastestConcat(list: List<String>): String {
    return list.joinToString("")  // 使用标准库函数
}

// 使用字符串模板 vs 连接
val name = "Alice"
val age = 25

// 好:使用模板
val message1 = "Name: $name, Age: $age"

// 不好:使用连接
val message2 = "Name: " + name + ", Age: " + age

4. 内存优化

Kotlin 复制代码
// 使用value class减少内存分配
@JvmInline
value class UserId(val value: Long)  // 运行时作为基本类型

@JvmInline
value class Email(val value: String)  // 编译时类型安全,运行时无开销

// 使用数组存储大量相同类型对象
data class Point(val x: Double, val y: Double)

// 不好:List<Point>,每个Point都是独立对象
val pointsList = List(1000000) { Point(it.toDouble(), it.toDouble()) }

// 好:使用平行数组
val xArray = DoubleArray(1000000) { it.toDouble() }
val yArray = DoubleArray(1000000) { it.toDouble() }

// 使用缓存避免重复计算
private val cache = mutableMapOf<Int, BigInteger>()

fun fibonacci(n: Int): BigInteger = cache.getOrPut(n) {
    if (n <= 1) BigInteger.valueOf(n.toLong())
    else fibonacci(n - 1) + fibonacci(n - 2)
}

三十二、Kotlin最佳实践

1. 代码风格指南

Kotlin 复制代码
// 1. 使用val代替var(不可变性)
val immutableList = listOf(1, 2, 3)  // 推荐
var mutableList = mutableListOf(1, 2, 3)  // 只在需要时使用

// 2. 使用数据类替代POJO
data class User(val id: Long, val name: String, val email: String)  // 推荐
// 自动生成equals, hashCode, toString, copy, componentN

// 3. 使用默认参数代替重载
fun connect(
    host: String = "localhost",
    port: Int = 8080,
    timeout: Int = 5000
) { /* ... */ }

// 4. 使用命名参数提高可读性
connect(
    host = "example.com",
    port = 443,
    timeout = 10000
)

// 5. 使用扩展函数增强可读性
fun String.isEmail(): Boolean = 
    this.matches(Regex("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}$"))

// 使用
if (email.isEmail()) { /* ... */ }

// 6. 使用when表达式代替复杂的if-else
fun describeNumber(n: Int): String = when {
    n < 0 -> "负数"
    n == 0 -> "零"
    n in 1..10 -> "小的正数"
    else -> "大的正数"
}

// 7. 使用作用域函数简化代码
// 使用apply进行对象配置
val dialog = AlertDialog.Builder(context).apply {
    setTitle("提示")
    setMessage("确定要删除吗?")
    setPositiveButton("确定") { _, _ -> /* ... */ }
    setNegativeButton("取消", null)
}.create()

// 使用let处理可空对象
val length = nullableString?.let { 
    println("Processing: $it")
    it.length 
} ?: 0

2. 错误处理最佳实践

Kotlin 复制代码
// 1. 使用Result类型处理可能失败的操作
fun parseNumber(str: String): Result<Int> = runCatching {
    str.toInt()
}

// 使用
val result = parseNumber("123")
result.onSuccess { number -> 
    println("Parsed number: $number")
}.onFailure { error ->
    println("Failed to parse: ${error.message}")
}

// 2. 使用密封类表示操作结果
sealed class ApiResult<out T> {
    data class Success<T>(val data: T) : ApiResult<T>()
    data class Error(val message: String, val code: Int) : ApiResult<Nothing>()
    object Loading : ApiResult<Nothing>()
}

// 3. 使用require/check进行参数验证
fun divide(a: Int, b: Int): Int {
    require(b != 0) { "除数不能为零" }
    check(a >= 0) { "被除数必须非负" }
    return a / b
}

// 4. 使用also进行调试和日志记录
val processedData = data
    .also { println("原始数据: $it") }
    .map { it * 2 }
    .also { println("处理后的数据: $it") }

3. 协程最佳实践

Kotlin 复制代码
// 1. 使用结构化并发
suspend fun fetchUserData(userId: String): UserData = coroutineScope {
    val userDeferred = async { api.getUser(userId) }
    val postsDeferred = async { api.getPosts(userId) }
    
    UserData(
        user = userDeferred.await(),
        posts = postsDeferred.await()
    )
}

// 2. 正确处理取消
suspend fun longRunningTask() = withContext(Dispatchers.IO) {
    repeat(1000) { i ->
        ensureActive()  // 检查协程是否被取消
        delay(100)
        println("Processing $i")
    }
}

// 3. 使用SupervisorJob处理子协程失败
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

scope.launch {
    // 即使这个子协程失败,其他子协程仍会继续
    throw RuntimeException("Failed!")
}

scope.launch {
    // 这个协程会继续执行
    delay(1000)
    println("Still running")
}

// 4. 使用适当的调度器
suspend fun processData() {
    // CPU密集型操作
    withContext(Dispatchers.Default) {
        // 计算、排序、转换等
    }
    
    // IO操作
    withContext(Dispatchers.IO) {
        // 文件读写、网络请求等
    }
    
    // UI更新
    withContext(Dispatchers.Main) {
        // 更新UI
    }
}

三十三、测试与调试

1. 单元测试

Kotlin 复制代码
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify

class CalculatorTest {
    private lateinit var calculator: Calculator
    
    @BeforeEach
    fun setUp() {
        calculator = Calculator()
    }
    
    @Test
    @DisplayName("测试加法")
    fun testAdd() {
        // 给定
        val a = 5
        val b = 3
        
        // 当
        val result = calculator.add(a, b)
        
        // 那么
        assertEquals(8, result)
    }
    
    @Test
    @DisplayName("测试除以零")
    fun testDivideByZero() {
        // 给定
        val a = 10
        val b = 0
        
        // 当/那么
        assertThrows<ArithmeticException> {
            calculator.divide(a, b)
        }
    }
    
    @ParameterizedTest
    @CsvSource(
        "2, 3, 5",
        "0, 0, 0",
        "-5, 10, 5",
        "100, -50, 50"
    )
    fun `parameterized test for addition`(a: Int, b: Int, expected: Int) {
        assertEquals(expected, calculator.add(a, b))
    }
    
    @Test
    fun `test with mock`() {
        // 创建mock对象
        val repository = mockk<UserRepository>()
        val service = UserService(repository)
        
        // 设置mock行为
        every { repository.findById(1) } returns User(1, "Alice")
        every { repository.findById(2) } returns null
        
        // 执行测试
        val user1 = service.getUser(1)
        val user2 = service.getUser(2)
        
        // 验证
        assertEquals("Alice", user1?.name)
        assertNull(user2)
        verify(exactly = 2) { repository.findById(any()) }
    }
}

// 使用Kotest进行更地道的Kotlin测试
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import io.kotest.property.Arb
import io.kotest.property.arbitrary.int
import io.kotest.property.checkAll

class CalculatorSpec : StringSpec({
    "加法应该返回正确结果" {
        val calculator = Calculator()
        calculator.add(2, 3) shouldBe 5
        calculator.add(-1, 1) shouldBe 0
    }
    
    "除以零应该抛出异常" {
        val calculator = Calculator()
        shouldThrow<ArithmeticException> {
            calculator.divide(10, 0)
        }
    }
    
    "属性测试:加法交换律" {
        checkAll(Arb.int(), Arb.int()) { a, b ->
            val calculator = Calculator()
            calculator.add(a, b) shouldBe calculator.add(b, a)
        }
    }
})

2. Android测试

Kotlin 复制代码
// Android单元测试
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
    @Test
    fun useAppContext() {
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        assertEquals("com.example.app", appContext.packageName)
    }
}

// Android UI测试
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
    @get:Rule
    val activityRule = ActivityScenarioRule(MainActivity::class.java)
    
    @Test
    fun testButtonClick() {
        // 检查初始状态
        onView(withId(R.id.textView))
            .check(matches(withText("Hello World!")))
        
        // 执行点击
        onView(withId(R.id.button))
            .perform(click())
        
        // 验证结果
        onView(withId(R.id.textView))
            .check(matches(withText("Button Clicked!")))
    }
}

// ViewModel测试
@ExperimentalCoroutinesApi
class UserViewModelTest {
    private lateinit var viewModel: UserViewModel
    private lateinit var userRepository: UserRepository
    
    @get:Rule
    var mainCoroutineRule = MainCoroutineRule()
    
    @Before
    fun setup() {
        userRepository = mockk()
        viewModel = UserViewModel(userRepository)
    }
    
    @Test
    fun `loadUser should update user LiveData`() = runBlockingTest {
        // 给定
        val user = User(1, "Alice")
        coEvery { userRepository.getUser(1) } returns user
        
        // 当
        viewModel.loadUser(1)
        
        // 那么
        val result = viewModel.user.getOrAwaitValue()
        assertEquals(user, result)
    }
}

3. 调试技巧

Kotlin 复制代码
// 1. 使用debug标记
inline fun <T> debug(block: () -> T): T {
    return if (BuildConfig.DEBUG) {
        val start = System.currentTimeMillis()
        val result = block()
        val end = System.currentTimeMillis()
        println("Debug: Execution time = ${end - start}ms")
        result
    } else {
        block()
    }
}

// 使用
val result = debug {
    // 需要调试的代码
    expensiveComputation()
}

// 2. 使用also进行调试
data.process()
    .also { println("第一步结果: $it") }
    .transform()
    .also { println("转换后结果: $it") }
    .filter { it.isValid() }
    .also { println("最终结果: $it") }

// 3. 条件断点
fun complexFunction(data: List<Int>) {
    data.forEach { item ->
        // 右键点击行号 -> 条件断点
        // 条件: item > 100 && item < 200
        processItem(item)
    }
}

// 4. 日志工具类
object Logger {
    private const val TAG = "MyApp"
    
    inline fun <reified T> T.log(level: LogLevel = LogLevel.DEBUG, message: () -> String) {
        if (shouldLog(level)) {
            val tag = if (T::class == Logger::class) TAG else T::class.simpleName
            println("[$tag] ${level.name}: ${message()}")
        }
    }
    
    enum class LogLevel { DEBUG, INFO, WARN, ERROR }
    
    private fun shouldLog(level: LogLevel): Boolean {
        return BuildConfig.DEBUG || level >= LogLevel.WARN
    }
}

// 使用
class UserService {
    fun getUser(id: Int): User? {
        Logger.log { "Getting user with id: $id" }
        // ...
    }
}

三十四、Kotlin工具链与构建

1. Gradle配置

bash 复制代码
// build.gradle.kts
plugins {
    kotlin("jvm") version "1.8.0"
    kotlin("plugin.spring") version "1.8.0"
    kotlin("kapt") version "1.8.0"
}

dependencies {
    // Kotlin标准库
    implementation(kotlin("stdlib"))
    implementation(kotlin("stdlib-jdk8"))
    implementation(kotlin("stdlib-jdk7"))
    implementation(kotlin("reflect"))
    
    // 协程
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
    
    // 序列化
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
    
    // 测试
    testImplementation(kotlin("test"))
    testImplementation(kotlin("test-junit"))
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
    
    // Mocking
    testImplementation("io.mockk:mockk:1.13.4")
    
    // Ktor (Web框架)
    implementation("io.ktor:ktor-server-core:2.2.3")
    implementation("io.ktor:ktor-server-netty:2.2.3")
}

tasks {
    compileKotlin {
        kotlinOptions {
            jvmTarget = "11"
            freeCompilerArgs = listOf("-Xjsr305=strict")
            allWarningsAsErrors = true
        }
    }
    
    compileTestKotlin {
        kotlinOptions {
            jvmTarget = "11"
            freeCompilerArgs = listOf("-Xjsr305=strict")
        }
    }
}

// 配置Kapt(注解处理)
kapt {
    correctErrorTypes = true
    useBuildCache = true
}

2. KSP(Kotlin Symbol Processing)

Kotlin 复制代码
// 1. 创建KSP处理器
// build.gradle.kts
plugins {
    kotlin("jvm")
    id("com.google.devtools.ksp") version "1.8.0-1.0.9"
}

dependencies {
    implementation("com.google.devtools.ksp:symbol-processing-api:1.8.0-1.0.9")
    ksp("com.example:my-processor:1.0.0")
}

// 2. 定义注解
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class JsonSerializable

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
annotation class JsonName(val name: String)

// 3. 实现KSP处理器
class JsonProcessor(
    private val codeGenerator: CodeGenerator,
    private val logger: KSPLogger
) : SymbolProcessor {
    
    override fun process(resolver: Resolver): List<KSAnnotated> {
        val symbols = resolver
            .getSymbolsWithAnnotation(JsonSerializable::class.qualifiedName!!)
            .filterIsInstance<KSClassDeclaration>()
        
        symbols.forEach { classDeclaration ->
            generateJsonAdapter(classDeclaration)
        }
        
        return emptyList()
    }
    
    private fun generateJsonAdapter(classDeclaration: KSClassDeclaration) {
        val packageName = classDeclaration.packageName.asString()
        val className = "${classDeclaration.simpleName.asString()}JsonAdapter"
        
        val file = codeGenerator.createNewFile(
            dependencies = Dependencies(true),
            packageName = packageName,
            fileName = className
        )
        
        file.writeText("""
            |package $packageName
            |
            |import kotlinx.serialization.*
            |import kotlinx.serialization.json.*
            |
            |class ${className} {
            |    fun toJson(obj: ${classDeclaration.simpleName.asString()}): String {
            |        return Json.encodeToString(obj)
            |    }
            |    
            |    fun fromJson(json: String): ${classDeclaration.simpleName.asString()} {
            |        return Json.decodeFromString(json)
            |    }
            |}
        """.trimMargin())
        
        file.close()
    }
}

// 4. 使用生成的代码
@JsonSerializable
data class User(
    @JsonName("user_name")
    val name: String,
    val age: Int,
    val email: String
)

// KSP会自动生成 UserJsonAdapter 类

3. 编译器插件

Kotlin 复制代码
// 1. 使用无符号类型
val uint: UInt = 42u
val ulong: ULong = 1000uL
val ushort: UShort = 65535u
val ubyte: UByte = 255u

// 2. 使用内联类编译器插件
// build.gradle.kts
kotlin {
    sourceSets.all {
        languageSettings {
            optIn("kotlin.ExperimentalUnsignedTypes")
            optIn("kotlin.ExperimentalStdlibApi")
            optIn("kotlin.time.ExperimentalTime")
        }
    }
}

// 3. 使用编译器参数优化
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
    kotlinOptions {
        // 启用内联类
        freeCompilerArgs += "-Xinline-classes"
        
        // 启用新的类型推断
        freeCompilerArgs += "-Xnew-inference"
        
        // 启用协程调试
        freeCompilerArgs += "-Xcoroutines=debug"
        
        // 启用实验性功能
        freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
        
        // 启用JVM默认方法
        freeCompilerArgs += "-Xjvm-default=all"
    }
}

三十五、Kotlin迁移策略

1. 渐进式迁移策略

Kotlin 复制代码
// 策略1:新文件用Kotlin,旧文件逐步迁移
// Java文件
public class UserService {
    public User getUser(int id) {
        // Java代码
        return userRepository.findById(id);
    }
}

// Kotlin新文件
class ProductService(
    private val productRepository: ProductRepository
) {
    fun getProduct(id: Int): Product? {
        return productRepository.findById(id)
    }
}

// 策略2:在Java中调用Kotlin代码
// Kotlin文件
@file:JvmName("StringUtils")  // 指定生成的Java类名

fun capitalize(str: String): String {
    return str.replaceFirstChar { it.uppercase() }
}

// Java中调用
String result = StringUtils.capitalize("hello");

// 策略3:使用混合项目结构
// src/main/java/ - 存放Java代码
// src/main/kotlin/ - 存放Kotlin代码
// src/test/kotlin/ - 测试代码用Kotlin编写

2. 自动转换工具

Kotlin 复制代码
// Android Studio/IntelliJ IDEA 提供自动转换
// 1. 打开Java文件
// 2. 选择 Code -> Convert Java File to Kotlin File
// 3. 手动修复转换后的问题

// 转换示例
// Java代码
public class User {
    private String name;
    private int age;
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}

// 转换后的Kotlin代码
class User(val name: String, val age: Int) {
    override fun toString(): String {
        return "User{name='$name', age=$age}"
    }
}

// 进一步优化为数据类
data class User(val name: String, val age: Int)

3. 常见迁移问题与解决方案

Kotlin 复制代码
// 问题1:静态成员迁移
// Java静态工具类
public class StringUtils {
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}

// Kotlin解决方案1:顶层函数
// StringUtils.kt
fun isEmpty(str: String?): Boolean {
    return str.isNullOrBlank()
}

// Kotlin解决方案2:伴生对象
class StringUtils {
    companion object {
        @JvmStatic
        fun isEmpty(str: String?): Boolean {
            return str.isNullOrBlank()
        }
    }
}

// 问题2:Builder模式迁移
// Java Builder模式
public class User {
    private final String name;
    private final int age;
    
    private User(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }
    
    public static class Builder {
        private String name;
        private int age;
        
        public Builder setName(String name) {
            this.name = name;
            return this;
        }
        
        public Builder setAge(int age) {
            this.age = age;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

// Kotlin解决方案:默认参数 + apply
data class User(
    val name: String,
    val age: Int
) {
    companion object {
        fun create(block: Builder.() -> Unit): User {
            return Builder().apply(block).build()
        }
    }
    
    class Builder {
        var name: String = ""
        var age: Int = 0
        
        fun build(): User = User(name, age)
    }
}

// 使用
val user = User.create {
    name = "Alice"
    age = 25
}

// 问题3:单例模式迁移
// Java单例
public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

// Kotlin解决方案:object关键字
object Singleton {
    fun doSomething() {
        println("Singleton operation")
    }
}

// 问题4:工具类迁移
// Java工具类
public final class CollectionUtils {
    private CollectionUtils() {}
    
    public static <T> boolean isEmpty(Collection<T> collection) {
        return collection == null || collection.isEmpty();
    }
}

// Kotlin解决方案:扩展函数
fun <T> Collection<T>?.isEmpty(): Boolean {
    return this == null || this.isEmpty()
}

// 使用
val list: List<String>? = null
if (list.isEmpty()) {
    println("List is empty")
}

4. 测试迁移

三十六、Kotlin特性总结与Java对比

1. 核心特性对比表

|-----------------|----------------------------------------------|-----------------------------------------|-------------|
| 特性 | Java | Kotlin | 优势 |
| 空安全 | @Nullable / @NotNull 注解 | 类型系统内置 (String? / String) | 编译时检查,减少NPE |
| 类型推断 | var (Java 10+) 有限支持 | 全面的类型推断 (val x = 10) | 代码更简洁 |
| 数据类 | 需要手动编写getter/setter/equals等 | data class User(val name: String) | 自动生成样板代码 |
| 扩展函数 | 静态工具类 | fun String.capitalize(): String | 增强现有类,无需继承 |
| 默认参数 | 方法重载 | fun greet(name: String = "Guest") | 减少重载方法数量 |
| 命名参数 | 不支持 | connect(host="localhost", port=8080) | 提高可读性 |
| 字符串模板 | "Hello, " + name + "!" | "Hello, $name!" | 更简洁易读 |
| when表达式 | switch语句 | when (x) { ... } | 更强大,支持任意类型 |
| 属性 | 字段+getter/setter | var name: String | 统一访问方式 |
| 委托 | 需要手动实现委托模式 | by关键字 | 简化委托模式实现 |
| 协程 | Thread / ExecutorService / CompletableFuture | suspend函数 + 协程 | 简化异步编程 |
| 密封类 | 枚举+类层次 | sealed class Result | 类型安全的代数数据类型 |
| 内联类 | 包装类(有开销) | value class Password(val value: String) | 类型安全,无运行时开销 |

2. 性能对比

Kotlin 复制代码
// Kotlin性能优化点:

// 1. 内联函数消除lambda开销
inline fun <T> measureTime(block: () -> T): T {
    val start = System.currentTimeMillis()
    val result = block()
    val end = System.currentTimeMillis()
    println("Time: ${end - start}ms")
    return result
}

// 2. 使用基本类型数组
val intArray = IntArray(1000000)  // 基本类型,无装箱
val integerList = List(1000000) { it }  // 装箱类型

// 3. 使用序列进行惰性求值
val result = (1..1000000)
    .asSequence()           // 转换为序列
    .filter { it % 2 == 0 } // 惰性操作
    .map { it * 2 }         // 惰性操作
    .take(1000)             // 只取前1000个
    .toList()               // 最终计算

// 4. 使用局部函数避免重复计算
fun processData(data: List<Int>): List<String> {
    // 局部函数,可以访问外部变量
    fun isValid(value: Int): Boolean {
        return value > 0 && value < 100
    }
    
    return data.filter(::isValid).map { it.toString() }
}

3. 互操作最佳实践

Kotlin 复制代码
// 1. 为Java调用优化Kotlin代码
class KotlinClass {
    companion object {
        @JvmStatic  // 生成静态方法
        fun staticMethod() { }
        
        @JvmField   // 生成公共字段
        val CONSTANT = "value"
    }
    
    @JvmOverloads  // 生成重载方法
    fun method(param: String = "default") { }
}

// 2. 处理Java平台类型
fun processJavaList(list: List<String>) {  // List<String>! 平台类型
    // 安全处理
    val safeList: List<String> = list ?: emptyList()
    
    // 或使用扩展函数
    list.orEmpty().forEach { println(it) }
}

// 3. 使用@JvmName解决签名冲突
@JvmName("filterStrings")
fun List<String>.filter(predicate: (String) -> Boolean): List<String> {
    return this.filter(predicate)
}

@JvmName("filterInts")
fun List<Int>.filter(predicate: (Int) -> Boolean): List<Int> {
    return this.filter(predicate)
}

// 4. 异常处理互操作
@Throws(IOException::class)  // 为Java声明受检异常
fun readFile(path: String): String {
    return File(path).readText()
}

三十七、学习资源与进阶路径

1. 官方资源

2. 书籍推荐

  • 《Kotlin in Action》 - Dmitry Jemerov & Svetlana Isakova
  • 《Kotlin Programming: The Big Nerd Ranch Guide》 - Josh Skeen & David Greenhalgh
  • 《Head First Kotlin》 - Dawn Griffiths & David Griffiths
  • 《Effective Kotlin》 - Marcin Moskała

3. 在线课程

  • Kotlin Bootcamp for Programmers (Google)
  • Kotlin for Java Developers (JetBrains on Coursera)
  • Android Kotlin Fundamentals (Google)

4. 社区资源

  • Kotlin Slack : kotlinlang.slack.com
  • Reddit : r/kotlin
  • Stack Overflow : kotlin标签
  • GitHub : kotlin/kotlin 仓库

5. 工具与框架

bash 复制代码
// 常用框架
dependencies {
    // Web框架
    implementation("io.ktor:ktor-server-core:2.3.0")
    implementation("io.ktor:ktor-server-netty:2.3.0")
    
    // HTTP客户端
    implementation("io.ktor:ktor-client-core:2.3.0")
    implementation("io.ktor:ktor-client-okhttp:2.3.0")
    
    // 序列化
    implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.0")
    
    // 数据库
    implementation("org.jetbrains.exposed:exposed-core:0.40.1")
    implementation("org.jetbrains.exposed:exposed-dao:0.40.1")
    implementation("org.jetbrains.exposed:exposed-jdbc:0.40.1")
    
    // 依赖注入
    implementation("org.koin:koin-core:3.3.3")
    
    // 测试
    testImplementation("io.kotest:kotest-runner-junit5:5.5.5")
    testImplementation("io.mockk:mockk:1.13.4")
}

// 开发工具
// 1. IntelliJ IDEA / Android Studio
// 2. Kotlin Plugin
// 3. ktlint (代码风格检查)
// 4. detekt (静态代码分析)
// 5. gradle-kotlin-dsl (Gradle Kotlin DSL)

三十八、实战项目结构示例

// 典型的Kotlin多模块项目结构

project/

├── build.gradle.kts

├── settings.gradle.kts

├── buildSrc/

│ └── src/main/kotlin/Dependencies.kt

├── core/

│ └── src/main/kotlin/com/example/core/

├── feature-auth/

│ └── src/main/kotlin/com/example/auth/

├── feature-user/ # 用户功能模块

│ ├── build.gradle.kts

│ └── src/main/kotlin/com/example/user/

│ ├── di/

│ ├── domain/

│ ├── data/

│ └── presentation/

├── app/ # 应用模块

│ ├── build.gradle.kts

│ └── src/main/kotlin/com/example/app/

│ ├── di/

│ ├── Main.kt # 应用入口

│ └── config/

└── shared/ # 共享模块

├── build.gradle.kts

└── src/commonMain/kotlin/ # 多平台共享代码

三十九、代码规范与最佳实践

1. 命名规范

Kotlin 复制代码
// 包名:全小写,不使用下划线
package com.example.myproject

// 类/接口:大驼峰
class UserRepository
interface DataSource

// 函数/变量:小驼峰
fun calculateTotalPrice()
val userCount: Int

// 常量:大写+下划线
const val MAX_RETRY_COUNT = 3
const val API_BASE_URL = "https://api.example.com"

// 测试函数:使用反引号
@Test
fun `should return user when valid id provided`() {
    // 测试代码
}

// 扩展函数:明确的前缀
fun String.toSlug(): String
fun View.show()
fun View.hide()

// 工厂函数:使用伴生对象
class User private constructor(val id: String) {
    companion object {
        fun create(id: String): User {
            return User(id)
        }
    }
}

2. 代码风格

Kotlin 复制代码
// 1. 使用表达式体
fun isEven(number: Int): Boolean = number % 2 == 0

// 2. 使用默认参数
fun connect(
    host: String = "localhost",
    port: Int = 8080,
    timeout: Int = 5000
) { /* ... */ }

// 3. 使用命名参数
connect(
    host = "api.example.com",
    port = 443,
    timeout = 10000
)

// 4. 使用数据类
data class User(
    val id: Long,
    val name: String,
    val email: String,
    val createdAt: Instant = Instant.now()
)

// 5. 使用密封类处理状态
sealed class ApiState<out T> {
    object Loading : ApiState<Nothing>()
    data class Success<T>(val data: T) : ApiState<T>()
    data class Error(val message: String) : ApiState<Nothing>()
}

// 6. 使用when表达式
fun describeNumber(n: Int): String = when {
    n < 0 -> "负数"
    n == 0 -> "零"
    n in 1..10 -> "小的正数"
    else -> "大的正数"
}

// 7. 使用扩展函数
fun String.isValidEmail(): Boolean {
    return matches(Regex("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}$"))
}

// 8. 使用作用域函数
val user = User(
    id = 1,
    name = "Alice",
    email = "alice@example.com"
).also { 
    logger.info("User created: $it") 
}

3. 错误处理模式

Kotlin 复制代码
// 1. 使用Result类型
fun parseNumber(str: String): Result<Int> = runCatching {
    str.toInt()
}

// 使用
parseNumber("123").fold(
    onSuccess = { println("Parsed: $it") },
    onFailure = { println("Failed: ${it.message}") }
)

// 2. 使用Either类型
sealed class Either<out L, out R> {
    data class Left<out L>(val value: L) : Either<L, Nothing>()
    data class Right<out R>(val value: R) : Either<Nothing, R>()
}

fun divide(a: Int, b: Int): Either<String, Int> {
    return if (b == 0) {
        Either.Left("除数不能为零")
    } else {
        Either.Right(a / b)
    }
}

// 3. 使用验证器模式
data class ValidationResult(
    val isValid: Boolean,
    val errors: List<String> = emptyList()
)

class Validator<T> {
    private val validations = mutableListOf<(T) -> ValidationResult>()
    
    fun addValidation(validation: (T) -> ValidationResult) {
        validations.add(validation)
    }
    
    fun validate(value: T): ValidationResult {
        val errors = validations
            .map { it(value) }
            .filter { !it.isValid }
            .flatMap { it.errors }
        
        return ValidationResult(errors.isEmpty(), errors)
    }
}

// 使用
val userValidator = Validator<User>().apply {
    addValidation { user ->
        if (user.name.isBlank()) {
            ValidationResult(false, listOf("姓名不能为空"))
        } else {
            ValidationResult(true)
        }
    }
    
    addValidation { user ->
        if (!user.email.isValidEmail()) {
            ValidationResult(false, listOf("邮箱格式不正确"))
        } else {
            ValidationResult(true)
        }
    }
}

四十、常见陷阱与解决方案

1. 空安全陷阱

Kotlin 复制代码
// 陷阱1:使用!!非空断言
val length: Int = nullableString!!.length  // 可能抛出NPE

// 解决方案:使用安全调用或默认值
val length1: Int? = nullableString?.length  // 安全调用
val length2: Int = nullableString?.length ?: 0  // Elvis操作符

// 陷阱2:平台类型
val javaList: List<String> = JavaClass.getList()  // List<String>! 平台类型

// 解决方案:明确类型
val kotlinList:
Kotlin 复制代码
// 陷阱2:平台类型
val javaList: List<String> = JavaClass.getList()  // List<String>! 平台类型

// 解决方案:明确类型
val kotlinList: List<String> = JavaClass.getList() ?: emptyList()
val safeList = JavaClass.getList().orEmpty()

// 陷阱3:lateinit var 未初始化
class UserService {
    private lateinit var repository: UserRepository
    
    fun initialize() {
        // 忘记初始化 repository
    }
    
    fun getUser(id: Int): User? {
        return repository.findById(id)  // 运行时抛出异常:lateinit property repository has not been initialized
    }
}

// 解决方案1:使用可为空类型
class UserService {
    private var repository: UserRepository? = null
    
    fun initialize(repo: UserRepository) {
        repository = repo
    }
    
    fun getUser(id: Int): User? {
        return repository?.findById(id)
    }
}

// 解决方案2:使用依赖注入
class UserService(private val repository: UserRepository) {
    fun getUser(id: Int): User? {
        return repository.findById(id)
    }
}

// 解决方案3:使用 lazy 初始化
class UserService {
    private val repository by lazy {
        UserRepository()
    }
    
    fun getUser(id: Int): User? {
        return repository.findById(id)
    }
}

2. 集合陷阱

Kotlin 复制代码
// 陷阱1:误用可变集合
val list = listOf(1, 2, 3)  // 不可变列表
list.add(4)  // 编译错误

val mutableList = mutableListOf(1, 2, 3)  // 可变列表
mutableList.add(4)  // 正确

// 陷阱2:集合拷贝
val original = mutableListOf(1, 2, 3)
val copy = original  // 这只是引用拷贝,不是内容拷贝
copy.add(4)
println(original)  // [1, 2, 3, 4] 原集合也被修改了

// 解决方案:使用 toList() 或 toMutableList()
val safeCopy = original.toList()  // 创建新列表
// 或
val mutableCopy = original.toMutableList()

// 陷阱3:集合操作性能
val largeList = (1..1_000_000).toList()

// 低效:多次中间集合
val result1 = largeList
    .filter { it % 2 == 0 }      // 创建中间集合
    .map { it * 2 }              // 创建中间集合
    .take(1000)                  // 创建中间集合
    .toList()

// 高效:使用序列
val result2 = largeList.asSequence()
    .filter { it % 2 == 0 }      // 惰性操作
    .map { it * 2 }              // 惰性操作
    .take(1000)                  // 惰性操作
    .toList()                    // 最终计算

// 陷阱4:集合与数组转换
val list = listOf(1, 2, 3)
val array: Array<Int> = list.toTypedArray()  // 装箱的 Integer 数组
val intArray: IntArray = list.toIntArray()   // 基本类型 int 数组(更高效)

3. 类型系统陷阱

Kotlin 复制代码
// 陷阱1:类型擦除
fun <T> checkType(obj: Any): Boolean {
    return obj is T  // 编译警告:Cannot check for instance of erased type: T
}

// 解决方案:使用 reified 和内联函数
inline fun <reified T> checkTypeReified(obj: Any): Boolean {
    return obj is T  // 正确
}

// 陷阱2:协变和逆变
open class Animal
class Dog : Animal()
class Cat : Animal()

// 协变:只能读取,不能写入
val animals: List<Animal> = listOf(Dog(), Cat())  // 正确
val dogs: List<Dog> = listOf(Dog())
// animals = dogs  // 编译错误

// 逆变:只能写入,不能读取
interface Consumer<in T> {
    fun consume(item: T)
}

val animalConsumer: Consumer<Animal> = object : Consumer<Animal> {
    override fun consume(item: Animal) { /* ... */ }
}

val dogConsumer: Consumer<Dog> = animalConsumer  // 正确,逆变
// dogConsumer.consume(Dog())  // 实际上调用的是 animalConsumer.consume(Dog())

// 陷阱3:星投影
fun printList(list: List<*>) {
    // list 的元素类型是未知的
    for (item in list) {
        println(item)  // item 的类型是 Any?
    }
    // list.add(anything)  // 编译错误:不能添加元素
}

// 正确使用
fun <T> processList(list: List<T>, processor: (T) -> Unit) {
    for (item in list) {
        processor(item)
    }
}

4. 函数式编程陷阱

Kotlin 复制代码
// 陷阱1:过度使用链式调用
val result = list
    .filter { it > 0 }
    .map { it * 2 }
    .sorted()
    .distinct()
    .take(10)
    .joinToString()

// 解决方案:考虑可读性和性能
val result = list
    .asSequence()  // 对于大数据集使用序列
    .filter { it > 0 }
    .map { it * 2 }
    .sorted()
    .distinct()
    .take(10)
    .joinToString()

// 陷阱2:误用 let/also/apply/run
val user = User().apply {
    name = "Alice"
    age = 25
}.also {
    println("Created user: $it")
}.let {
    it.copy(email = "${it.name.lowercase()}@example.com")
}

// 选择合适的作用域函数:
// - apply: 对象配置,返回对象本身
// - also: 附加操作,返回对象本身
// - let: 转换对象,返回lambda结果
// - run: 对象配置和计算,返回lambda结果
// - with: 在对象上执行操作,返回lambda结果

// 陷阱3:高阶函数性能
// 内联函数适合小型lambda,非内联函数适合大型lambda
inline fun <T> processInline(items: List<T>, processor: (T) -> Unit) {
    // 适合:processor很小,内联可以提升性能
    for (item in items) {
        processor(item)
    }
}

fun <T> processNoInline(items: List<T>, processor: (T) -> Unit) {
    // 适合:processor很大,避免代码膨胀
    for (item in items) {
        processor(item)
    }
}

5. 协程陷阱

Kotlin 复制代码
// 陷阱1:忘记处理取消
suspend fun longRunningTask() {
    repeat(1000) { i ->
        // 忘记检查取消状态
        delay(100)
        println("Processing $i")
    }
}

// 解决方案:使用 ensureActive 或 yield
suspend fun longRunningTaskFixed() = coroutineScope {
    repeat(1000) { i ->
        ensureActive()  // 检查是否被取消
        // 或 yield()
        delay(100)
        println("Processing $i")
    }
}

// 陷阱2:阻塞主线程
fun loadData() {
    // 错误:在UI线程启动长时间运行的任务
    GlobalScope.launch(Dispatchers.Main) {
        val data = fetchData()  // 挂起函数,但可能阻塞
        updateUI(data)
    }
}

// 解决方案:使用适当的调度器
fun loadDataCorrect() {
    viewModelScope.launch {
        // 在IO线程执行网络请求
        val data = withContext(Dispatchers.IO) {
            fetchData()
        }
        // 在主线程更新UI
        withContext(Dispatchers.Main) {
            updateUI(data)
        }
    }
}

// 陷阱3:异常处理不当
fun riskyOperation() {
    GlobalScope.launch {
        try {
            throw RuntimeException("Error!")
        } catch (e: Exception) {
            // 异常被捕获,但协程仍然崩溃
        }
    }
}

// 解决方案:使用 CoroutineExceptionHandler 或 SupervisorJob
fun safeOperation() {
    val exceptionHandler = CoroutineExceptionHandler { _, exception ->
        println("Caught $exception")
    }
    
    val scope = CoroutineScope(SupervisorJob() + exceptionHandler)
    
    scope.launch {
        throw RuntimeException("Error!")  // 被exceptionHandler捕获
    }
    
    scope.launch {
        delay(1000)
        println("This still runs")  // 仍然执行
    }
}

// 陷阱4:内存泄漏
class MyActivity : AppCompatActivity() {
    private val scope = CoroutineScope(Dispatchers.Main)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        scope.launch {
            // 长时间运行的任务
            delay(5000)
            updateUI()  // Activity可能已经被销毁!
        }
    }
    
    override fun onDestroy() {
        super.onDestroy()
        scope.cancel()  // 必须手动取消!
    }
}

// 解决方案1:使用lifecycleScope(Android)
class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        lifecycleScope.launch {
            // 自动跟随生命周期
            delay(5000)
            if (isActive) {  // 检查是否仍然活跃
                updateUI()
            }
        }
    }
}

// 解决方案2:使用viewModelScope(ViewModel)
class MyViewModel : ViewModel() {
    fun loadData() {
        viewModelScope.launch {
            val data = repository.fetchData()
            _data.value = data
        }
    }
}

// 解决方案3:结构化并发
suspend fun fetchUserData(userId: String): UserData = coroutineScope {
    val userDeferred = async { api.getUser(userId) }
    val postsDeferred = async { api.getPosts(userId) }
    
    try {
        UserData(
            user = userDeferred.await(),
            posts = postsDeferred.await()
        )
    } catch (e: Exception) {
        // 如果任何一个子协程失败,所有子协程都会被取消
        throw e
    }
}

// 陷阱5:并发修改共享状态
class Counter {
    var count = 0
    
    suspend fun increment() {
        // 危险:多个协程可能同时修改
        count++
    }
}

// 解决方案1:使用Mutex
class SafeCounter {
    private var count = 0
    private val mutex = Mutex()
    
    suspend fun increment() {
        mutex.withLock {
            count++
        }
    }
    
    suspend fun getCount(): Int {
        return mutex.withLock { count }
    }
}

// 解决方案2:使用Actor
sealed class CounterMessage
object Increment : CounterMessage()
class GetCount(val response: CompletableDeferred<Int>) : CounterMessage()

fun CoroutineScope.counterActor() = actor<CounterMessage> {
    var count = 0
    
    for (msg in channel) {
        when (msg) {
            is Increment -> count++
            is GetCount -> msg.response.complete(count)
        }
    }
}

// 使用
val counter = counterActor()

suspend fun testActor() {
    repeat(1000) {
        launch {
            counter.send(Increment)
        }
    }
    
    delay(1000)
    val response = CompletableDeferred<Int>()
    counter.send(GetCount(response))
    println("Count: ${response.await()}")
    counter.close()
}

四十一、Android开发特有转换

1. Activity和Fragment

Kotlin 复制代码
// Java Activity
public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private Button button;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        textView = findViewById(R.id.text_view);
        button = findViewById(R.id.button);
        
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.setText("Button Clicked!");
            }
        });
    }
}

// Kotlin Activity
class MainActivity : AppCompatActivity() {
    // 使用视图绑定或DataBinding
    private lateinit var binding: ActivityMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        binding.button.setOnClickListener {
            binding.textView.text = "Button Clicked!"
        }
    }
}

// 使用Kotlin扩展简化
fun AppCompatActivity.toast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

fun View.onClick(action: () -> Unit) {
    setOnClickListener { action() }
}

// 简化后的Activity
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        binding.button.onClick {
            binding.textView.text = "Button Clicked!"
            toast("Button clicked!")
        }
    }
}

2. ViewModel和LiveData

Kotlin 复制代码
// Java ViewModel
public class UserViewModel extends ViewModel {
    private MutableLiveData<User> user = new MutableLiveData<>();
    private UserRepository repository = new UserRepository();
    
    public LiveData<User> getUser() {
        return user;
    }
    
    public void loadUser(int userId) {
        repository.getUser(userId, new Callback<User>() {
            @Override
            public void onSuccess(User result) {
                user.setValue(result);
            }
            
            @Override
            public void onError(Exception e) {
                // 处理错误
            }
        });
    }
}

// Kotlin ViewModel
class UserViewModel : ViewModel() {
    private val repository = UserRepository()
    
    private val _user = MutableLiveData<User>()
    val user: LiveData<User> = _user
    
    private val _loading = MutableLiveData<Boolean>()
    val loading: LiveData<Boolean> = _loading
    
    private val _error = MutableLiveData<String>()
    val error: LiveData<String> = _error
    
    fun loadUser(userId: Int) {
        viewModelScope.launch {
            _loading.value = true
            try {
                val result = repository.getUser(userId)
                _user.value = result
            } catch (e: Exception) {
                _error.value = e.message
            } finally {
                _loading.value = false
            }
        }
    }
}

// 使用StateFlow(替代LiveData)
class UserViewModel : ViewModel() {
    private val repository = UserRepository()
    
    private val _userState = MutableStateFlow<UserState>(UserState.Loading)
    val userState: StateFlow<UserState> = _userState
    
    fun loadUser(userId: Int) {
        viewModelScope.launch {
            _userState.value = UserState.Loading
            try {
                val user = repository.getUser(userId)
                _userState.value = UserState.Success(user)
            } catch (e: Exception) {
                _userState.value = UserState.Error(e.message ?: "Unknown error")
            }
        }
    }
}

sealed class UserState {
    object Loading : UserState()
    data class Success(val user: User) : UserState()
    data class Error(val message: String) : UserState()
}

3. RecyclerView适配器

Kotlin 复制代码
// Java适配器
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {
    private List<User> users = new ArrayList<>();
    
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_user, parent, false);
        return new ViewHolder(view);
    }
    
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        User user = users.get(position);
        holder.nameTextView.setText(user.getName());
        holder.emailTextView.setText(user.getEmail());
    }
    
    @Override
    public int getItemCount() {
        return users.size();
    }
    
    public void setUsers(List<User> users) {
        this.users = users;
        notifyDataSetChanged();
    }
    
    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView nameTextView;
        TextView emailTextView;
        
        ViewHolder(View itemView) {
            super(itemView);
            nameTextView = itemView.findViewById(R.id.name_text_view);
            emailTextView = itemView.findViewById(R.id.email_text_view);
        }
    }
}

// Kotlin适配器(使用ViewBinding)
class UserAdapter : RecyclerView.Adapter<UserAdapter.ViewHolder>() {
    private var users: List<User> = emptyList()
    
    var onItemClick: ((User) -> Unit)? = null
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemUserBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
        return ViewHolder(binding)
    }
    
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val user = users[position]
        holder.bind(user)
        
        holder.itemView.setOnClickListener {
            onItemClick?.invoke(user)
        }
    }
    
    override fun getItemCount(): Int = users.size
    
    fun submitList(newUsers: List<User>) {
        val diffResult = DiffUtil.calculateDiff(UserDiffCallback(users, newUsers))
        users = newUsers
        diffResult.dispatchUpdatesTo(this)
    }
    
    class ViewHolder(
        private val binding: ItemUserBinding
    ) : RecyclerView.ViewHolder(binding.root) {
        fun bind(user: User) {
            binding.nameTextView.text = user.name
            binding.emailTextView.text = user.email
            binding.ageTextView.text = user.age.toString()
            
            // 使用扩展函数加载图片
            binding.avatarImageView.load(user.avatarUrl) {
                placeholder(R.drawable.placeholder)
                error(R.drawable.error)
            }
        }
    }
    
    class UserDiffCallback(
        private val oldList: List<User>,
        private val newList: List<User>
    ) : DiffUtil.Callback() {
        override fun getOldListSize(): Int = oldList.size
        override fun getNewListSize(): Int = newList.size
        
        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            return oldList[oldItemPosition].id == newList[newItemPosition].id
        }
        
        override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            return oldList[oldItemPosition] == newList[newItemPosition]
        }
    }
}

// 使用ListAdapter简化
class UserListAdapter : ListAdapter<User, UserListAdapter.ViewHolder>(UserDiffCallback()) {
    
    class ViewHolder(
        private val binding: ItemUserBinding
    ) : RecyclerView.ViewHolder(binding.root) {
        fun bind(user: User) {
            binding.user = user
            binding.executePendingBindings()
        }
    }
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemUserBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
        return ViewHolder(binding)
    }
    
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(getItem(position))
    }
    
    class UserDiffCallback : DiffUtil.ItemCallback<User>() {
        override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
            return oldItem.id == newItem.id
        }
        
        override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
            return oldItem == newItem
        }
    }
}

4. 网络请求(Retrofit + Coroutines)

Kotlin 复制代码
// Java Retrofit接口
public interface ApiService {
    @GET("users/{id}")
    Call<User> getUser(@Path("id") int userId);
    
    @POST("users")
    Call<User> createUser(@Body User user);
}

// Kotlin Retrofit接口(使用协程)
interface ApiService {
    @GET("users/{id}")
    suspend fun getUser(@Path("id") userId: Int): User
    
    @POST("users")
    suspend fun createUser(@Body user: User): User
    
    @GET("users")
    suspend fun getUsers(@Query("page") page: Int): List<User>
    
    @Multipart
    @POST("upload")
    suspend fun uploadFile(@Part file: MultipartBody.Part): UploadResponse
}

// 使用Kotlin扩展简化Retrofit
inline fun <reified T> createApiService(baseUrl: String): T {
    return Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(T::class.java)
}

// 或者使用Ktor客户端(纯Kotlin)
val httpClient = HttpClient(CIO) {
    install(ContentNegotiation) {
        json(Json {
            prettyPrint = true
            isLenient = true
        })
    }
    install(Logging) {
        level = LogLevel.HEADERS
    }
}

suspend fun fetchUser(userId: Int): User {
    return httpClient.get("https://api.example.com/users/$userId")
}

// Repository模式
class UserRepository(
    private val apiService: ApiService,
    private val database: UserDatabase
) {
    private val cache = mutableMapOf<Int, User>()
    
    suspend fun getUser(userId: Int): User {
        // 先从缓存获取
        cache[userId]?.let { return it }
        
        // 然后从数据库获取
        val localUser = database.userDao().getById(userId)
        if (localUser != null) {
            cache[userId] = localUser
            return localUser
        }
        
        // 最后从网络获取
        return try {
            val remoteUser = apiService.getUser(userId)
            database.userDao().insert(remoteUser)
            cache[userId] = remoteUser
            remoteUser
        } catch (e: Exception) {
            throw UserNotFoundException("User not found: $userId", e)
        }
    }
    
    suspend fun getUsers(page: Int): List<User> {
        return try {
            val users = apiService.getUsers(page)
            database.userDao().insertAll(users)
            users
        } catch (e: Exception) {
            // 网络失败时返回本地数据
            database.userDao().getAll()
        }
    }
}

5. 数据库(Room + Coroutines)

Kotlin 复制代码
// Java Room实体
@Entity(tableName = "users")
public class User {
    @PrimaryKey
    public int id;
    
    @ColumnInfo(name = "user_name")
    public String name;
    
    public String email;
    
    @Ignore
    public String temporaryField;
}

// Kotlin Room实体
@Entity(tableName = "users")
data class User(
    @PrimaryKey
    val id: Int,
    
    @ColumnInfo(name = "user_name")
    val name: String,
    
    val email: String,
    
    @ColumnInfo(defaultValue = "CURRENT_TIMESTAMP")
    val createdAt: Date = Date()
) {
    // 忽略的字段
    @Ignore
    var temporaryField: String? = null
}

// DAO接口
@Dao
interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(user: User)
    
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAll(users: List<User>)
    
    @Update
    suspend fun update(user: User)
    
    @Delete
    suspend fun delete(user: User)
    
    @Query("SELECT * FROM users WHERE id = :userId")
    suspend fun getById(userId: Int): User?
    
    @Query("SELECT * FROM users ORDER BY name ASC")
    fun getAll(): Flow<List<User>>
    
    @Query("SELECT * FROM users WHERE name LIKE :query")
    suspend fun search(query: String): List<User>
    
    @Transaction
    suspend fun updateWithLog(user: User) {
        update(user)
        // 可以执行多个操作
    }
}

// 数据库类
@Database(
    entities = [User::class, Post::class],
    version = 1,
    exportSchema = false
)
@TypeConverters(DateConverter::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
    abstract fun postDao(): PostDao
    
    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null
        
        fun getDatabase(context: Context): AppDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "app_database"
                )
                .addCallback(object : RoomDatabase.Callback() {
                    override fun onCreate(db: SupportSQLiteDatabase) {
                        super.onCreate(db)
                        // 数据库创建时的操作
                    }
                })
                .build()
                INSTANCE = instance
                instance
            }
        }
    }
}

// 类型转换器
class DateConverter {
    @TypeConverter
    fun fromTimestamp(value: Long?): Date? {
        return value?.let { Date(it) }
    }
    
    @TypeConverter
    fun dateToTimestamp(date: Date?): Long? {
        return date?.time
    }
}

四十二、 Android开发中的Kotlin实践指南

1. build.gradle配置

Kotlin 复制代码
// 项目级 build.gradle.kts
plugins {
    id("com.android.application") version "8.0.0" apply false
    id("com.android.library") version "8.0.0" apply false
    id("org.jetbrains.kotlin.android") version "1.8.0" apply false
    id("com.google.dagger.hilt.android") version "2.44" apply false
}

// 模块级 build.gradle.kts
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("kotlin-kapt")
    id("dagger.hilt.android.plugin")
    id("androidx.navigation.safeargs.kotlin")
}

android {
    namespace = "com.example.myapp"
    compileSdk = 33

    defaultConfig {
        applicationId = "com.example.myapp"
        minSdk = 24
        targetSdk = 33
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
    }

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

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }

    kotlinOptions {
        jvmTarget = "11"
        freeCompilerArgs = listOf(
            "-Xopt-in=kotlin.RequiresOptIn",
            "-Xjvm-default=all"
        )
    }

    buildFeatures {
        viewBinding = true
        dataBinding = true
        compose = true  // 如果使用Compose
    }

    composeOptions {
        kotlinCompilerExtensionVersion = "1.4.0"
    }
}

dependencies {
    // Kotlin
    implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.0")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")

    // AndroidX Core
    implementation("androidx.core:core-ktx:1.9.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("androidx.activity:activity-ktx:1.6.1")
    implementation("androidx.fragment:fragment-ktx:1.5.5")

    // UI
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    implementation("com.google.android.material:material:1.8.0")
    implementation("androidx.recyclerview:recyclerview:1.3.0")
    implementation("androidx.viewpager2:viewpager2:1.0.0")

    // Lifecycle
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
    implementation("androidx.lifecycle:lifecycle-common-java8:2.6.1")

    // Navigation
    implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
    implementation("androidx.navigation:navigation-ui-ktx:2.5.3")

    // Room
    implementation("androidx.room:room-runtime:2.5.0")
    implementation("androidx.room:room-ktx:2.5.0")
    kapt("androidx.room:room-compiler:2.5.0")

    // Hilt
    implementation("com.google.dagger:hilt-android:2.44")
    kapt("com.google.dagger:hilt-compiler:2.44")

    // Networking
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    implementation("com.squareup.okhttp3:okhttp:4.10.0")
    implementation("com.squareup.okhttp3:logging-interceptor:4.10.0")

    // Image Loading
    implementation("io.coil-kt:coil:2.2.2")

    // Timber (Logging)
    implementation("com.jakewharton.timber:timber:5.0.1")

    // Testing
    testImplementation("junit:junit:4.13.2")
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
    testImplementation("io.mockk:mockk:1.13.4")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}

二、常用扩展函数

Kotlin 复制代码
// ViewExtensions.kt
import android.view.View

fun View.show() {
    visibility = View.VISIBLE
}

fun View.hide() {
    visibility = View.GONE
}

fun View.invisible() {
    visibility = View.INVISIBLE
}

fun View.isVisible(): Boolean = visibility == View.VISIBLE

fun View.isGone(): Boolean = visibility == View.GONE

fun View.isInvisible(): Boolean = visibility == View.INVISIBLE

fun View.onClick(delay: Long = 200, action: () -> Unit) {
    setOnClickListener {
        it.isClickable = false
        action()
        it.postDelayed({ it.isClickable = true }, delay)
    }
}

// ContextExtensions.kt
import android.content.Context
import android.widget.Toast

fun Context.toast(message: String, duration: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, duration).show()
}

fun Context.showLongToast(message: String) {
    toast(message, Toast.LENGTH_LONG)
}

fun Context.dpToPx(dp: Float): Int {
    return (dp * resources.displayMetrics.density).toInt()
}

fun Context.pxToDp(px: Int): Float {
    return px / resources.displayMetrics.density
}

// StringExtensions.kt
fun String?.orEmpty(): String = this ?: ""

fun String?.isNotNullOrEmpty(): Boolean = !this.isNullOrEmpty()

fun String?.isNotNullOrBlank(): Boolean = !this.isNullOrBlank()

fun String.capitalizeWords(): String {
    return split(" ").joinToString(" ") { word ->
        word.replaceFirstChar { it.uppercase() }
    }
}

// ListExtensions.kt
fun <T> List<T>?.orEmpty(): List<T> = this ?: emptyList()

fun <T> List<T>.secondOrNull(): T? = getOrNull(1)

fun <T> List<T>.secondLastOrNull(): T? = getOrNull(size - 2)

// SharedPreferences扩展
import android.content.SharedPreferences

fun SharedPreferences.edit(block: SharedPreferences.Editor.() -> Unit) {
    val editor = edit()
    editor.block()
    editor.apply()
}

inline fun <reified T> SharedPreferences.get(key: String, defaultValue: T): T {
    return when (T::class) {
        String::class -> getString(key, defaultValue as? String) as T
        Int::class -> getInt(key, defaultValue as? Int ?: 0) as T
        Long::class -> getLong(key, defaultValue as? Long ?: 0L) as T
        Float::class -> getFloat(key, defaultValue as? Float ?: 0f) as T
        Boolean::class -> getBoolean(key, defaultValue as? Boolean ?: false) as T
        else -> throw IllegalArgumentException("Unsupported type")
    }
}

// Bundle扩展
import android.os.Bundle

fun Bundle.put(key: String, value: Any?) {
    when (value) {
        null -> putString(key, null)
        is String -> putString(key, value)
        is Int -> putInt(key, value)
        is Long -> putLong(key, value)
        is Float -> putFloat(key, value)
        is Boolean -> putBoolean(key, value)
        is Bundle -> putBundle(key, value)
        is Parcelable -> putParcelable(key, value)
        is Serializable -> putSerializable(key, value)
        else -> throw IllegalArgumentException("Unsupported type: ${value.javaClass}")
    }
}

三、ViewModel与LiveData

Kotlin 复制代码
// BaseViewModel.kt
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

abstract class BaseViewModel : ViewModel() {
    protected val _loading = MutableStateFlow(false)
    val loading: StateFlow<Boolean> = _loading
    
    protected val _error = MutableStateFlow<String?>(null)
    val error: StateFlow<String?> = _error
    
    protected val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
        viewModelScope.launch {
            _error.value = throwable.message ?: "未知错误"
        }
    }
    
    protected fun launchWithLoading(block: suspend () -> Unit) {
        viewModelScope.launch(exceptionHandler) {
            _loading.value = true
            try {
                block()
            } finally {
                _loading.value = false
            }
        }
    }
    
    fun clearError() {
        _error.value = null
    }
}

// UserViewModel.kt
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch

class UserViewModel(
    private val userRepository: UserRepository
) : BaseViewModel() {
    
    private val _userState = MutableStateFlow<UserState>(UserState.Idle)
    val userState: StateFlow<UserState> = _userState
    
    private val _users = MutableStateFlow<List<User>>(emptyList())
    val users: StateFlow<List<User>> = _users
    
    fun loadUser(userId: Int) {
        launchWithLoading {
            userRepository.getUser(userId)
                .onStart { _userState.value = UserState.Loading }
                .catch { error ->
                    _userState.value = UserState.Error(error.message ?: "加载失败")
                }
                .collect { user ->
                    _userState.value = UserState.Success(user)
                }
        }
    }
    
    fun loadUsers() {
        viewModelScope.launch {
            userRepository.getUsers()
                .onStart { _loading.value = true }
                .catch { error ->
                    _error.value = error.message
                }
                .collect { users ->
                    _users.value = users
                }
        }
    }
    
    fun searchUsers(query: String) {
        viewModelScope.launch {
            userRepository.searchUsers(query)
                .debounce(300)  // 防抖
                .distinctUntilChanged()
                .collect { users ->
                    _users.value = users
                }
        }
    }
    
    fun updateUser(user: User) {
        launchWithLoading {
            userRepository.updateUser(user)
            // 更新本地状态
            _users.update { list ->
                list.map { if (it.id == user.id) user else it }
            }
        }
    }
    
    fun deleteUser(userId: Int) {
        launchWithLoading {
            userRepository.deleteUser(userId)
            // 更新本地状态
            _users.update { list ->
                list.filter { it.id != userId }
            }
        }
    }
}

// 状态封装
sealed class UserState {
    object Idle : UserState()
    object Loading : UserState()
    data class Success(val user: User) : UserState()
    data class Error(val message: String) : UserState()
}

// Repository实现
class UserRepositoryImpl(
    private val apiService: ApiService,
    private val userDao: UserDao
) : UserRepository {
    
    override fun getUser(userId: Int): Flow<User> = flow {
        // 先尝试从数据库获取
        val cachedUser = userDao.getUserById(userId)
        cachedUser?.let { emit(it) }
        
        // 从网络获取
        try {
            val remoteUser = apiService.getUser(userId)
            userDao.insert(remoteUser)
            emit(remoteUser)
        } catch (e: Exception) {
            if (cachedUser == null) {
                throw e  // 没有缓存数据,抛出异常
            }
            // 有缓存数据,使用缓存
        }
    }
    
    override fun getUsers(): Flow<List<User>> = flow {
        // 监听数据库变化
        userDao.getAllUsers().collect { cachedUsers ->
            emit(cachedUsers)
        }
        
        // 同时从网络获取最新数据
        try {
            val remoteUsers = apiService.getUsers()
            userDao.insertAll(remoteUsers)
        } catch (e: Exception) {
            // 网络失败,使用缓存数据
        }
    }
    
    override suspend fun updateUser(user: User) {
        try {
            val updatedUser = apiService.updateUser(user.id, user)
            userDao.insert(updatedUser)
        } catch (e: Exception) {
            // 先更新本地,稍后同步
            userDao.insert(user.copy(isSynced = false))
            throw e
        }
    }
}

四、Compose UI开发

Kotlin 复制代码
// 1. 主题配置
@Composable
fun MyAppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }
    
    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}

// 2. 主界面
@Composable
fun MainScreen(
    viewModel: MainViewModel = hiltViewModel()
) {
    val userState by viewModel.userState.collectAsState()
    val users by viewModel.users.collectAsState()
    
    MyAppTheme {
        Scaffold(
            topBar = {
                TopAppBar(
                    title = { Text("用户列表") },
                    actions = {
                        IconButton(onClick = { viewModel.refresh() }) {
                            Icon(Icons.Filled.Refresh, "刷新")
                        }
                    }
                )
            },
            floatingActionButton = {
                FloatingActionButton(onClick = { /* 添加用户 */ }) {
                    Icon(Icons.Filled.Add, "添加")
                }
            }
        ) { padding ->
            when (val state = userState) {
                is UserState.Loading -> LoadingScreen()
                is UserState.Error -> ErrorScreen(state.message) {
                    viewModel.refresh()
                }
                is UserState.Success -> UserListScreen(
                    users = users,
                    onUserClick = { user ->
                        // 导航到用户详情
                    },
                    modifier = Modifier.padding(padding)
                )
                UserState.Idle -> {}
            }
        }
    }
}

// 3. 用户列表
@Composable
fun UserListScreen(
    users: List<User>,
    onUserClick: (User) -> Unit,
    modifier: Modifier = Modifier
) {
    LazyColumn(modifier = modifier.fillMaxSize()) {
        items(users, key = { it.id }) { user ->
            UserItem(
                user = user,
                onClick = { onUserClick(user) }
            )
        }
    }
}

@Composable
fun UserItem(
    user: User,
    onClick: () -> Unit
) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp, vertical = 8.dp)
            .clickable(onClick = onClick),
        elevation = 4.dp
    ) {
        Row(
            modifier = Modifier.padding(16.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            AsyncImage(
                model = user.avatarUrl,
                contentDescription = "用户头像",
                modifier = Modifier
                    .size(48.dp)
                    .clip(CircleShape),
                contentScale = ContentScale.Crop
            )
            
            Spacer(modifier = Modifier.width(16.dp))
            
            Column {
                Text(
                    text = user.name,
                    style = MaterialTheme.typography.h6,
                    fontWeight = FontWeight.Bold
                )
                
                Spacer(modifier = Modifier.height(4.dp))
                
                Text(
                    text = user.email,
                    style = MaterialTheme.typography.body2,
                    color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
                )
            }
            
            Spacer(modifier = Modifier.weight(1f))
            
            Icon(
                imageVector = Icons.Default.ArrowForward,
                contentDescription = "查看详情",
                tint = MaterialTheme.colors.primary
            )
        }
    }
}

// 4. 加载和错误状态
@Composable
fun LoadingScreen() {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        CircularProgressIndicator()
    }
}
@Composable
fun ErrorScreen(
    message: String,
    onRetry: () -> Unit
) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Icon(
            imageVector = Icons.Filled.Error,
            contentDescription = "错误",
            tint = MaterialTheme.colors.error,
            modifier = Modifier.size(64.dp)
        )
        
        Spacer(modifier = Modifier.height(16.dp))
        
        Text(
            text = "出错了",
            style = MaterialTheme.typography.h6,
            color = MaterialTheme.colors.error
        )
        
        Spacer(modifier = Modifier.height(8.dp))
        
        Text(
            text = message,
            style = MaterialTheme.typography.body2,
            textAlign = TextAlign.Center,
            color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
        )
        
        Spacer(modifier = Modifier.height(24.dp))
        
        Button(
            onClick = onRetry,
            colors = ButtonDefaults.buttonColors(
                backgroundColor = MaterialTheme.colors.primary
            )
        ) {
            Text(text = "重试")
        }
    }
}

// 5. 表单输入
@Composable
fun LoginScreen(
    viewModel: LoginViewModel = hiltViewModel()
) {
    val email by viewModel.email.collectAsState()
    val password by viewModel.password.collectAsState()
    val isLoading by viewModel.isLoading.collectAsState()
    val error by viewModel.error.collectAsState()
    
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(32.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = "登录",
            style = MaterialTheme.typography.h4,
            fontWeight = FontWeight.Bold,
            modifier = Modifier.padding(bottom = 32.dp)
        )
        
        OutlinedTextField(
            value = email,
            onValueChange = viewModel::onEmailChange,
            label = { Text("邮箱") },
            placeholder = { Text("请输入邮箱") },
            leadingIcon = { Icon(Icons.Default.Email, null) },
            isError = error?.contains("邮箱") == true,
            modifier = Modifier.fillMaxWidth()
        )
        
        Spacer(modifier = Modifier.height(16.dp))
        
        OutlinedTextField(
            value = password,
            onValueChange = viewModel::onPasswordChange,
            label = { Text("密码") },
            placeholder = { Text("请输入密码") },
            leadingIcon = { Icon(Icons.Default.Lock, null) },
            visualTransformation = PasswordVisualTransformation(),
            isError = error?.contains("密码") == true,
            modifier = Modifier.fillMaxWidth()
        )
        
        error?.let {
            Text(
                text = it,
                color = MaterialTheme.colors.error,
                style = MaterialTheme.typography.caption,
                modifier = Modifier.padding(top = 8.dp)
            )
        }
        
        Spacer(modifier = Modifier.height(24.dp))
        
        Button(
            onClick = viewModel::login,
            enabled = !isLoading,
            modifier = Modifier
                .fillMaxWidth()
                .height(48.dp)
        ) {
            if (isLoading) {
                CircularProgressIndicator(
                    modifier = Modifier.size(24.dp),
                    strokeWidth = 2.dp,
                    color = MaterialTheme.colors.onPrimary
                )
            } else {
                Text(text = "登录")
            }
        }
        
        Spacer(modifier = Modifier.height(16.dp))
        
        TextButton(onClick = { /* 跳转到注册 */ }) {
            Text(text = "没有账号?立即注册")
        }
    }
}

// 6. ViewModel for Compose
class LoginViewModel @Inject constructor(
    private val authRepository: AuthRepository
) : ViewModel() {
    private val _email = MutableStateFlow("")
    val email: StateFlow<String> = _email
    
    private val _password = MutableStateFlow("")
    val password: StateFlow<String> = _password
    
    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading
    
    private val _error = MutableStateFlow<String?>(null)
    val error: StateFlow<String?> = _error
    
    fun onEmailChange(newEmail: String) {
        _email.value = newEmail
        _error.value = null
    }
    
    fun onPasswordChange(newPassword: String) {
        _password.value = newPassword
        _error.value = null
    }
    
    fun login() {
        viewModelScope.launch {
            _isLoading.value = true
            _error.value = null
            
            val result = authRepository.login(
                email = _email.value,
                password = _password.value
            )
            
            _isLoading.value = false
            
            result.onSuccess { user ->
                // 登录成功,导航到主界面
            }.onFailure { exception ->
                _error.value = when (exception) {
                    is NetworkException -> "网络连接失败,请检查网络"
                    is AuthException -> "邮箱或密码错误"
                    else -> "登录失败,请重试"
                }
            }
        }
    }
}

五、导航(Navigation Component)

Kotlin 复制代码
// 1. 导航图定义
@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    
    NavHost(
        navController = navController,
        startDestination = "splash"
    ) {
        composable("splash") {
            SplashScreen(
                onNavigateToLogin = { navController.navigate("login") },
                onNavigateToHome = { navController.navigate("home") }
            )
        }
        
        composable("login") {
            LoginScreen(
                onLoginSuccess = { navController.navigate("home") },
                onNavigateToRegister = { navController.navigate("register") }
            )
        }
        
        composable("register") {
            RegisterScreen(
                onRegisterSuccess = { navController.navigate("home") },
                onNavigateToLogin = { navController.navigate("login") }
            )
        }
        
        composable("home") {
            HomeScreen(
                onNavigateToProfile = { userId ->
                    navController.navigate("profile/$userId")
                },
                onNavigateToSettings = { navController.navigate("settings") }
            )
        }
        
        composable(
            route = "profile/{userId}",
            arguments = listOf(navArgument("userId") { type = NavType.IntType })
        ) { backStackEntry ->
            val userId = backStackEntry.arguments?.getInt("userId") ?: 0
            ProfileScreen(
                userId = userId,
                onNavigateBack = { navController.popBackStack() }
            )
        }
        
        composable("settings") {
            SettingsScreen(
                onNavigateBack = { navController.popBackStack() }
            )
        }
    }
}

// 2. 带参数的导航
sealed class Screen(val route: String) {
    object Splash : Screen("splash")
    object Login : Screen("login")
    object Register : Screen("register")
    object Home : Screen("home")
    object Profile : Screen("profile/{userId}") {
        fun createRoute(userId: Int) = "profile/$userId"
    }
    object Settings : Screen("settings")
}

// 3. 导航工具类
class NavigationManager(
    private val navController: NavHostController
) {
    fun navigateToLogin() {
        navController.navigate(Screen.Login.route) {
            popUpTo(Screen.Splash.route) { inclusive = true }
        }
    }
    
    fun navigateToHome() {
        navController.navigate(Screen.Home.route) {
            popUpTo(0) { inclusive = true }
        }
    }
    
    fun navigateToProfile(userId: Int) {
        navController.navigate(Screen.Profile.createRoute(userId))
    }
    
    fun navigateBack() {
        navController.popBackStack()
    }
    
    fun navigateUp() {
        navController.navigateUp()
    }
}

// 4. 在ViewModel中使用导航
class HomeViewModel @Inject constructor(
    private val navigationManager: NavigationManager
) : ViewModel() {
    
    fun onProfileClick(userId: Int) {
        navigationManager.navigateToProfile(userId)
    }
    
    fun onSettingsClick() {
        navigationManager.navigateTo(Screen.Settings.route)
    }
    
    fun onBackPressed() {
        navigationManager.navigateBack()
    }
}

// 5. 深链接处理
composable(
    route = "details/{id}",
    arguments = listOf(navArgument("id") { type = NavType.StringType }),
    deepLinks = listOf(
        navDeepLink { uriPattern = "myapp://details/{id}" }
    )
) { backStackEntry ->
    val id = backStackEntry.arguments?.getString("id")
    DetailsScreen(id = id)
}

// 6. 底部导航
@Composable
fun MainScreen() {
    val navController = rememberNavController()
    
    Scaffold(
        bottomBar = {
            BottomNavigation {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentDestination = navBackStackEntry?.destination
                
                BottomNavigationItem(
                    icon = { Icon(Icons.Filled.Home, contentDescription = "首页") },
                    label = { Text("首页") },
                    selected = currentDestination?.route == "home",
                    onClick = {
                        navController.navigate("home") {
                            popUpTo(navController.graph.findStartDestination().id) {
                                saveState = true
                            }
                            launchSingleTop = true
                            restoreState = true
                        }
                    }
                )
                
                BottomNavigationItem(
                    icon = { Icon(Icons.Filled.Search, contentDescription = "搜索") },
                    label = { Text("搜索") },
                    selected = currentDestination?.route == "search",
                    onClick = {
                        navController.navigate("search") {
                            popUpTo(navController.graph.findStartDestination().id) {
                                saveState = true
                            }
                            launchSingleTop = true
                            restoreState = true
                        }
                    }
                )
                
                BottomNavigationItem(
                    icon = { Icon(Icons.Filled.Person, contentDescription = "我的") },
                    label = { Text("我的") },
                    selected = currentDestination?.route == "profile",
                    onClick = {
                        navController.navigate("profile") {
                            popUpTo(navController.graph.findStartDestination().id) {
                                saveState = true
                            }
                            launchSingleTop = true
                            restoreState = true
                        }
                    }
                )
            }
        }
    ) { paddingValues ->
        NavHost(
            navController = navController,
            startDestination = "home",
            modifier = Modifier.padding(paddingValues)
        ) {
            composable("home") { HomeScreen() }
            composable("search") { SearchScreen() }
            composable("profile") { ProfileScreen() }
        }
    }
}

// 7. 嵌套导航图
fun NavGraphBuilder.mainGraph(navController: NavController) {
    navigation(startDestination = "dashboard", route = "main") {
        composable("dashboard") { DashboardScreen() }
        composable("notifications") { NotificationsScreen() }
        composable("messages") { MessagesScreen() }
    }
}

fun NavGraphBuilder.authGraph(navController: NavController) {
    navigation(startDestination = "login", route = "auth") {
        composable("login") { LoginScreen() }
        composable("register") { RegisterScreen() }
        composable("forgotPassword") { ForgotPasswordScreen() }
    }
}

// 在主NavHost中使用
NavHost(navController, startDestination = "splash") {
    composable("splash") { SplashScreen() }
    authGraph(navController)
    mainGraph(navController)
}

六、依赖注入(Hilt)

Kotlin 复制代码
// 1. Application类
@HiltAndroidApp
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // 初始化代码
        if (BuildConfig.DEBUG) {
            Timber.plant(Timber.DebugTree())
        }
    }
}

// 2. 定义模块
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    
    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = if (BuildConfig.DEBUG) {
                    HttpLoggingInterceptor.Level.BODY
                } else {
                    HttpLoggingInterceptor.Level.NONE
                }
            })
            .addInterceptor { chain ->
                val request = chain.request().newBuilder()
                    .addHeader("Authorization", "Bearer ${getToken()}")
                    .build()
                chain.proceed(request)
            }
            .build()
    }
    
    @Provides
    @Singleton
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BuildConfig.BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .build()
    }
    
    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }
    
    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext context: Context): AppDatabase {
        return Room.databaseBuilder(
            context,
            AppDatabase::class.java,
            "app_database"
        )
        .fallbackToDestructiveMigration()
        .build()
    }
    
    @Provides
    @Singleton
    fun provideUserDao(database: AppDatabase): UserDao {
        return database.userDao()
    }
    
    @Provides
    @Singleton
    fun provideUserRepository(
        apiService: ApiService,
        userDao: UserDao
    ): UserRepository {
        return UserRepositoryImpl(apiService, userDao)
    }
}

// 3. ViewModel注入
@HiltViewModel
class UserViewModel @Inject constructor(
    private val userRepository: UserRepository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    // ViewModel逻辑
}

// 4. Activity/Fragment注入
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    
    @Inject
    lateinit var analytics: AnalyticsService
    
    @Inject
    lateinit var userManager: UserManager
    
    private val viewModel: MainViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 依赖已自动注入
    }
}

@AndroidEntryPoint
class UserFragment : Fragment() {
    
    private val viewModel: UserViewModel by viewModels()
    
    @Inject
    lateinit var imageLoader: ImageLoader
    
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // 依赖已自动注入
        return super.onCreateView(inflater, container, savedInstanceState)
    }
}

// 5. 自定义作用域
@InstallIn(ActivityComponent::class)
@Module
object ActivityModule {
    
    @Provides
    @ActivityScoped
    fun provideActivityContext(@ActivityContext context: Context): Context {
        return context
    }
}

@InstallIn(ViewComponent::class)
@Module
object ViewModule {
    
    @Provides
    @ViewScoped
    fun provideViewDependency(): ViewDependency {
        return ViewDependency()
    }
}

// 6. 限定符
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ApiUrl

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class AuthInterceptorOkHttpClient

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
    
    @Provides
    @ApiUrl
    fun provideApiUrl(): String = BuildConfig.BASE_URL
    
    @Provides
    @Singleton
    @AuthInterceptorOkHttpClient
    fun provideAuthOkHttpClient(
        authInterceptor: AuthInterceptor
    ): OkHttpClient {
        return OkHttpClient.Builder()
            .addInterceptor(authInterceptor)
            .build()
    }
    
    @Provides
    @Singleton
    fun provideRetrofit(
        @ApiUrl baseUrl: String,
        @AuthInterceptorOkHttpClient okHttpClient: OkHttpClient
    ): Retrofit {
        return Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .build()
    }
}

七、实用工具类

Kotlin 复制代码
// 1. 网络状态检查
object NetworkUtils {
    
    @SuppressLint("MissingPermission")
    fun isNetworkAvailable(context: Context): Boolean {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
            as ConnectivityManager
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val network = connectivityManager.activeNetwork
            val capabilities = connectivityManager.getNetworkCapabilities(network)
            return capabilities != null && (
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
            )
        } else {
            @Suppress("DEPRECATION")
            val networkInfo = connectivityManager.activeNetworkInfo
            return networkInfo != null && networkInfo.isConnected
        }
    }
    
    fun getNetworkType(context: Context): String {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
            as ConnectivityManager
        
        return when {
            connectivityManager.isActiveNetworkMetered -> "MOBILE"
            connectivityManager.isActiveNetworkWifi -> "WIFI"
            else -> "UNKNOWN"
        }
   }

// 2. 权限处理
object PermissionUtils {
    
    // 检查单个权限
    fun Context.hasPermission(permission: String): Boolean {
        return ContextCompat.checkSelfPermission(this, permission) ==
                PackageManager.PERMISSION_GRANTED
    }
    
    // 检查多个权限
    fun Context.hasPermissions(vararg permissions: String): Boolean {
        return permissions.all { hasPermission(it) }
    }
    
    // 请求权限的ActivityResult合约
    class RequestPermissions : ActivityResultContract<Array<String>, Map<String, Boolean>>() {
        override fun createIntent(context: Context, input: Array<String>): Intent {
            return Intent(ACTION_REQUEST_PERMISSIONS).putExtra(EXTRA_PERMISSIONS, input)
        }
        
        override fun parseResult(resultCode: Int, intent: Intent?): Map<String, Boolean> {
            if (resultCode != Activity.RESULT_OK) return emptyMap()
            
            val permissions = intent?.getStringArrayExtra(EXTRA_PERMISSIONS) ?: return emptyMap()
            val grantResults = intent.getIntArrayExtra(EXTRA_GRANT_RESULTS) ?: return emptyMap()
            
            return permissions.zip(grantResults.map { it == PackageManager.PERMISSION_GRANTED }).toMap()
        }
        
        companion object {
            const val ACTION_REQUEST_PERMISSIONS = "request_permissions"
            const val EXTRA_PERMISSIONS = "permissions"
            const val EXTRA_GRANT_RESULTS = "grant_results"
        }
    }
    
    // 在Activity/Fragment中使用
    class MainActivity : AppCompatActivity() {
        private val requestPermissions = registerForActivityResult(
            RequestPermissions()
        ) { results ->
            if (results.all { it.value }) {
                // 所有权限都已授予
                startCamera()
            } else {
                // 有些权限被拒绝
                showPermissionDeniedDialog()
            }
        }
        
        private fun checkAndRequestPermissions() {
            val permissions = arrayOf(
                Manifest.permission.CAMERA,
                Manifest.permission.RECORD_AUDIO
            )
            
            if (hasPermissions(*permissions)) {
                startCamera()
            } else {
                requestPermissions.launch(permissions)
            }
        }
    }
}

// 3. 文件操作工具
object FileUtils {
    
    // 获取应用缓存目录
    fun Context.getCacheDirPath(): String {
        return cacheDir.absolutePath
    }
    
    // 获取应用文件目录
    fun Context.getFilesDirPath(): String {
        return filesDir.absolutePath
    }
    
    // 获取外部存储目录
    fun Context.getExternalFilesDirPath(type: String? = null): String? {
        return getExternalFilesDir(type)?.absolutePath
    }
    
    // 检查存储权限
    fun Context.hasStoragePermission(): Boolean {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            Environment.isExternalStorageManager()
        } else {
            hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) &&
                    hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
        }
    }
    
    // 保存文本到文件
    fun Context.saveTextToFile(text: String, fileName: String): Boolean {
        return try {
            openFileOutput(fileName, Context.MODE_PRIVATE).use { output ->
                output.write(text.toByteArray())
            }
            true
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }
    
    // 从文件读取文本
    fun Context.readTextFromFile(fileName: String): String? {
        return try {
            openFileInput(fileName).use { input ->
                input.bufferedReader().use { reader ->
                    reader.readText()
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
    
    // 保存Bitmap到文件
    fun Context.saveBitmapToFile(bitmap: Bitmap, fileName: String): Boolean {
        return try {
            openFileOutput(fileName, Context.MODE_PRIVATE).use { output ->
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, output)
            }
            true
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }
    
    // 从文件读取Bitmap
    fun Context.readBitmapFromFile(fileName: String): Bitmap? {
        return try {
            BitmapFactory.decodeStream(openFileInput(fileName))
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
    
    // 获取文件大小
    fun getFileSize(file: File): String {
        val sizeInBytes = file.length()
        return when {
            sizeInBytes < 1024 -> "$sizeInBytes B"
            sizeInBytes < 1024 * 1024 -> "${sizeInBytes / 1024} KB"
            else -> "${sizeInBytes / (1024 * 1024)} MB"
        }
    }
    
    // 清理缓存
    fun Context.clearCache() {
        try {
            cacheDir.deleteRecursively()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

// 4. 图片处理工具
object ImageUtils {
    
    // 加载网络图片(使用Coil)
    fun ImageView.loadUrl(
        url: String,
        placeholder: Int = R.drawable.placeholder,
        error: Int = R.drawable.error
    ) {
        load(url) {
            placeholder(placeholder)
            error(error)
            crossfade(true)
        }
    }
    
    // 加载本地图片
    fun ImageView.loadFile(
        file: File,
        placeholder: Int = R.drawable.placeholder,
        error: Int = R.drawable.error
    ) {
        load(file) {
            placeholder(placeholder)
            error(error)
        }
    }
    
    // 加载资源图片
    fun ImageView.loadResource(
        @DrawableRes resId: Int,
        placeholder: Int = R.drawable.placeholder,
        error: Int = R.drawable.error
    ) {
        load(resId) {
            placeholder(placeholder)
            error(error)
        }
    }
    
    // 圆形图片
    fun ImageView.loadCircleImage(url: String) {
        load(url) {
            transformations(CircleCropTransformation())
        }
    }
    
    // 圆角图片
    fun ImageView.loadRoundedImage(
        url: String,
        cornerRadius: Float = 8.dp
    ) {
        load(url) {
            transformations(RoundedCornersTransformation(cornerRadius))
        }
    }
    
    // 高斯模糊
    fun ImageView.loadBlurImage(
        url: String,
        radius: Float = 10f,
        sampling: Float = 1f
    ) {
        load(url) {
            transformations(BlurTransformation(context, radius, sampling))
        }
    }
    
    // 保存图片到相册
    fun Context.saveImageToGallery(bitmap: Bitmap, title: String): Uri? {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            saveImageToGalleryApi29(bitmap, title)
        } else {
            saveImageToGalleryLegacy(bitmap, title)
        }
    }
    
    @RequiresApi(Build.VERSION_CODES.Q)
    private fun Context.saveImageToGalleryApi29(bitmap: Bitmap, title: String): Uri? {
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, "$title.jpg")
            put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
            put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
        }
        
        return contentResolver.insert(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            contentValues
        )?.also { uri ->
            contentResolver.openOutputStream(uri)?.use { output ->
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output)
            }
        }
    }
    
    @SuppressLint("MissingPermission")
    private fun Context.saveImageToGalleryLegacy(bitmap: Bitmap, title: String): Uri? {
        val imagesDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES
        )
        
        if (!imagesDir.exists()) {
            imagesDir.mkdirs()
        }
        
        val imageFile = File(imagesDir, "$title.jpg")
        
        return try {
            FileOutputStream(imageFile).use { output ->
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output)
            }
            
            MediaScannerConnection.scanFile(
                this,
                arrayOf(imageFile.absolutePath),
                arrayOf("image/jpeg"),
                null
            )
            
            Uri.fromFile(imageFile)
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    } 
    
    // 压缩图片
    fun compressImage(
        context: Context,
        imageUri: Uri,
        maxWidth: Int = 1024,
        maxHeight: Int = 1024,
        quality: Int = 80
    ): Bitmap? {
        return try {
            val options = BitmapFactory.Options().apply {
                inJustDecodeBounds = true
            }
            
            context.contentResolver.openInputStream(imageUri)?.use { input ->
                BitmapFactory.decodeStream(input, null, options)
            }
            
            // 计算采样率
            options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight)
            options.inJustDecodeBounds = false
            
            context.contentResolver.openInputStream(imageUri)?.use { input ->
                BitmapFactory.decodeStream(input, null, options)
            }
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
    
    private fun calculateInSampleSize(
        options: BitmapFactory.Options,
        reqWidth: Int,
        reqHeight: Int
    ): Int {
        val height = options.outHeight
        val width = options.outWidth
        var inSampleSize = 1
        
        if (height > reqHeight || width > reqWidth) {
            val halfHeight = height / 2
            val halfWidth = width / 2
            
            while ((halfHeight / inSampleSize) >= reqHeight &&
                   (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2
            }
        }
        
        return inSampleSize
    }
    
    // 创建圆形Bitmap
    fun createCircleBitmap(bitmap: Bitmap): Bitmap {
        val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)
        val paint = Paint().apply {
            isAntiAlias = true
        }
        
        val radius = min(bitmap.width, bitmap.height) / 2f
        
        canvas.drawCircle(
            bitmap.width / 2f,
            bitmap.height / 2f,
            radius,
            paint
        )
        
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(bitmap, 0f, 0f, paint)
        
        return output
    }
    
    // 创建圆角Bitmap
    fun createRoundedBitmap(bitmap: Bitmap, cornerRadius: Float): Bitmap {
        val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)
        val paint = Paint().apply {
            isAntiAlias = true
        }
        
        val rect = RectF(0f, 0f, bitmap.width.toFloat(), bitmap.height.toFloat())
        
        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint)
        
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(bitmap, 0f, 0f, paint)
        
        return output
    }
    
    // 调整Bitmap大小
    fun resizeBitmap(bitmap: Bitmap, newWidth: Int, newHeight: Int): Bitmap {
        return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true)
    }
    
    // 获取图片方向
    fun getImageOrientation(context: Context, imageUri: Uri): Int {
        return try {
            context.contentResolver.openInputStream(imageUri)?.use { input ->
                ExifInterface(input).getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL
                )
            } ?: ExifInterface.ORIENTATION_NORMAL
        } catch (e: Exception) {
            e.printStackTrace()
            ExifInterface.ORIENTATION_NORMAL
        }
    }
    
    // 旋转Bitmap
    fun rotateBitmap(bitmap: Bitmap, degrees: Float): Bitmap {
        val matrix = Matrix().apply {
            postRotate(degrees)
        }
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }
}

5. SharedPreferences扩展

Kotlin 复制代码
// SharedPreferences扩展函数
inline fun <reified T> SharedPreferences.get(
    key: String,
    defaultValue: T
): T {
    return when (T::class) {
        String::class -> getString(key, defaultValue as? String) as T
        Int::class -> getInt(key, defaultValue as? Int ?: 0) as T
        Long::class -> getLong(key, defaultValue as? Long ?: 0L) as T
        Float::class -> getFloat(key, defaultValue as? Float ?: 0f) as T
        Boolean::class -> getBoolean(key, defaultValue as? Boolean ?: false) as T
        Set::class -> getStringSet(key, defaultValue as? Set<String>) as T
        else -> throw IllegalArgumentException("Unsupported type")
    }
}

inline fun <reified T> SharedPreferences.Editor.put(
    key: String,
    value: T
): SharedPreferences.Editor {
    return when (T::class) {
        String::class -> putString(key, value as String)
        Int::class -> putInt(key, value as Int)
        Long::class -> putLong(key, value as Long)
        Float::class -> putFloat(key, value as Float)
        Boolean::class -> putBoolean(key, value as Boolean)
        Set::class -> putStringSet(key, value as Set<String>)
        else -> throw IllegalArgumentException("Unsupported type")
    }
}

// 数据存储管理器
class PreferenceManager(private val context: Context) {
    
    private val sharedPreferences: SharedPreferences by lazy {
        context.getSharedPreferences("app_preferences", Context.MODE_PRIVATE)
    }
    
    // 用户相关
    var authToken: String?
        get() = sharedPreferences.getString("auth_token", null)
        set(value) = sharedPreferences.edit { putString("auth_token", value) }
    
    var userId: Long
        get() = sharedPreferences.getLong("user_id", 0L)
        set(value) = sharedPreferences.edit { putLong("user_id", value) }
    
    var userName: String?
        get() = sharedPreferences.getString("user_name", null)
        set(value) = sharedPreferences.edit { putString("user_name", value) }
    
    var userEmail: String?
        get() = sharedPreferences.getString("user_email", null)
        set(value) = sharedPreferences.edit { putString("user_email", value) }
    
    // 应用设置
    var isDarkMode: Boolean
        get() = sharedPreferences.getBoolean("dark_mode", false)
        set(value) = sharedPreferences.edit { putBoolean("dark_mode", value) }
    
    var language: String
        get() = sharedPreferences.getString("language", "zh") ?: "zh"
        set(value) = sharedPreferences.edit { putString("language", value) }
    
    var notificationEnabled: Boolean
        get() = sharedPreferences.getBoolean("notification_enabled", true)
        set(value) = sharedPreferences.edit { putBoolean("notification_enabled", value) }
    
    // 首次启动
    var isFirstLaunch: Boolean
        get() = sharedPreferences.getBoolean("first_launch", true)
        set(value) = sharedPreferences.edit { putBoolean("first_launch", value) }
    
    // 清除所有数据
    fun clearAll() {
        sharedPreferences.edit().clear().apply()
    }
    
    // 清除用户相关数据
    fun clearUserData() {
        sharedPreferences.edit {
            remove("auth_token")
            remove("user_id")
            remove("user_name")
            remove("user_email")
        }.apply()
    }
}

// 使用示例
class MainActivity : AppCompatActivity() {
    private val preferenceManager by lazy { PreferenceManager(this) }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 检查是否首次启动
        if (preferenceManager.isFirstLaunch) {
            showWelcomeScreen()
            preferenceManager.isFirstLaunch = false
        }
        
        // 应用主题
        if (preferenceManager.isDarkMode) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
        } else {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
        }
        
        // 检查登录状态
        if (preferenceManager.authToken != null) {
            navigateToMainScreen()
        } else {
            navigateToLoginScreen()
        }
    }
    
    fun onLoginSuccess(token: String, user: User) {
        preferenceManager.authToken = token
        preferenceManager.userId = user.id
        preferenceManager.userName = user.name
        preferenceManager.userEmail = user.email
    }
    
    fun onLogout() {
        preferenceManager.clearUserData()
        navigateToLoginScreen()
    }
}
相关推荐
java1234_小锋9 小时前
Spring AI 2.0 开发Java Agent智能体 - 多模态支持
java·人工智能·spring
前端若水9 小时前
使用 IndexedDB 在客户端存储对话记录
java·前端·人工智能·python·机器学习
Flittly9 小时前
【日常小问】Spring Cloud Gateway 5.x 跨域和路由配置踩坑实录
java·spring boot·spring cloud
我不是懒洋洋9 小时前
大语言模型(LLM)入门:从Transformer到ChatGPT
c语言·开发语言·c++
MY_TEUCK9 小时前
【Java 后端 | 微服务远程调用实战】Nacos + OpenFeign 从入门到公共模块抽取
java·开发语言·微服务
love_muming9 小时前
Java编程核心技巧全解析
java·开发语言·idea
爱编程的小新☆9 小时前
Spring-AI入门
java·后端·spring
o丁二黄o10 小时前
语义版本控制:用Gemini镜像站实现合同条款的深度差异分析与风险追踪
javascript·kotlin·scala
wjm04100610 小时前
简单谈谈ios开发中的UI
开发语言·ios·swift