Android面试题库
Kotlin特性
Advanced Features

Kotlin 高级特性

密封类(Sealed Class)

概念和特点

  1. 定义

    • 限制类继承结构的类
    • 所有子类必须在同一文件中声明
    • 编译时类型安全
  2. 使用场景

    • 表示受限的类层次结构
    • 状态管理
    • 错误处理

示例代码

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>()
}
 
fun handleResult(result: Result<String>) = when (result) {
    is Result.Success -> println(result.data)
    is Result.Error -> println(result.exception.message)
    is Result.Loading -> println("Loading...")
    // 不需要else分支,编译器能确保所有情况都被处理
}

委托属性

核心概念

  1. 属性委托

    • 将属性的getter/setter委托给另一个类
    • 复用属性访问逻辑
    • 支持懒加载
  2. 内置委托

    • lazy
    • observable
    • vetoable
    • notNull

实现示例

// 自定义委托
class PreferenceDelegate<T>(
    private val context: Context,
    private val name: String,
    private val default: T
) {
    private val prefs by lazy {
        context.getSharedPreferences("default", Context.MODE_PRIVATE)
    }
 
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return findPreference(name, default)
    }
 
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        savePreference(name, value)
    }
}
 
// 使用示例
class SettingsManager(context: Context) {
    var username by PreferenceDelegate(context, "username", "")
    var isFirstLaunch by PreferenceDelegate(context, "isFirstLaunch", true)
}

内联类(Inline Class)

基本概念

  1. 特点

    • 在运行时表示为包装的类型
    • 编译时会被优化,减少内存分配
    • 只能有一个主构造器参数
  2. 使用场景

    • 度量单位转换
    • 类型安全的标识符
    • 性能优化

代码示例

@JvmInline
value class Password(private val value: String)
 
@JvmInline
value class Meters(val value: Double) {
    fun toKilometers(): Kilometers = Kilometers(value / 1000)
}
 
@JvmInline
value class Kilometers(val value: Double)
 
// 使用示例
fun login(username: String, password: Password) {
    // 类型安全的密码处理
}
 
val distance = Meters(5000.0).toKilometers()

扩展函数(Extension Functions)

核心特性

  1. 定义方式

    • 不修改原类的情况下添加新功能
    • 可以访问接收者的public成员
    • 支持泛型扩展
  2. 使用限制

    • 不能访问私有成员
    • 不能重写已有方法
    • 扩展属性不能有backing field

实践示例

// 字符串扩展
fun String.removeFirstAndLast() = substring(1, length - 1)
 
// 泛型扩展
fun <T> List<T>.swap(index1: Int, index2: Int): List<T> {
    val result = this.toMutableList()
    val tmp = result[index1]
    result[index1] = result[index2]
    result[index2] = tmp
    return result
}
 
// 扩展属性
val <T> List<T>.lastIndex: Int
    get() = size - 1

协程(Coroutines)

基础概念

  1. 特点

    • 轻量级线程
    • 支持异步编程
    • 结构化并发
  2. 核心组件

    • CoroutineScope
    • CoroutineContext
    • Job
    • Dispatcher

实现示例

// 基本使用
fun main() = runBlocking {
    launch {
        delay(1000)
        println("World!")
    }
    println("Hello")
}
 
// 异步操作
suspend fun fetchUser(): User = coroutineScope {
    val user = async { api.getUser() }
    val friends = async { api.getFriends() }
    user.await().copy(friends = friends.await())
}
 
// 错误处理
val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught $exception")
}
 
val job = GlobalScope.launch(handler) {
    throw AssertionError("My Custom Error")
}

面试题精选

1. 密封类和枚举类的区别是什么?

答案

  1. 密封类可以包含状态,而枚举常量不能
  2. 密封类的子类可以有多个实例,枚举常量只能有一个实例
  3. 密封类可以继承其他类,枚举类不能
  4. 密封类更适合表示复杂的状态层次结构

2. 什么是属性委托?有哪些常用的委托模式?

答案

  1. 属性委托是将属性的getter/setter委托给另一个类处理的机制
  2. 常用的委托模式:
    • lazy:懒加载
    • observable:观察属性变化
    • vetoable:可否决的属性修改
    • notNull:非空属性
    • map:将属性存储在Map中

3. 内联类的主要用途是什么?

答案

  1. 性能优化:避免运行时装箱操作
  2. 类型安全:提供特定类型的包装
  3. 零成本抽象:编译时会被优化掉
  4. 适用场景:
    • 度量单位转换
    • 类型安全的标识符
    • 性能敏感的包装类

4. 协程与线程的区别是什么?

答案

  1. 资源消耗:协程更轻量,可以创建大量实例
  2. 切换开销:协程切换成本低,不涉及线程切换
  3. 编程模型:协程支持结构化并发,代码更清晰
  4. 异常处理:协程提供内置的异常处理机制
  5. 取消机制:协程支持结构化取消

5. Kotlin的扩展函数有什么限制?

答案

  1. 不能访问接收者类的私有成员
  2. 不能重写已有的成员方法
  3. 扩展属性不能有backing field
  4. 扩展函数的解析是静态的
  5. 子类扩展函数不能覆盖父类扩展函数