Files
mkdocs/docs/android面试/基础知识/Kotlin基础.md
2026-01-15 11:53:37 +08:00

7.5 KiB
Raw Blame History

Kotlin基础

目录


基本语法

变量声明

// 可变变量
var name: String = "John"
name = "Jane"

// 不可变变量
val age: Int = 25
// age = 26 // 编译错误

// 类型推断
var count = 10 // 自动推断为 Int
var message = "Hello" // 自动推断为 String

函数定义

// 普通函数
fun add(a: Int, b: Int): Int {
    return a + b
}

// 单表达式函数
fun multiply(a: Int, b: Int) = a * b

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

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

控制流

// if 表达式
val max = if (a > b) a else b

// when 表达式(类似 switch
when (x) {
    1 -> println("One")
    2 -> println("Two")
    else -> println("Other")
}

// for 循环
for (i in 1..10) {
    println(i)
}

for (item in list) {
    println(item)
}

// while 循环
while (condition) {
    // 代码
}

空安全

可空类型

// 可空类型
var name: String? = null
name = "John"

// 安全调用
val length = name?.length // 如果 name 为 null返回 null

// Elvis 操作符
val length2 = name?.length ?: 0 // 如果 name 为 null返回 0

// 非空断言
val length3 = name!!.length // 如果 name 为 null抛出异常

空安全操作

// 安全调用链
val length = user?.address?.street?.length

// let 函数
name?.let {
    println(it.length)
}

// 类型检查
if (obj is String) {
    println(obj.length) // 自动转换为 String
}

扩展函数

扩展函数定义

// 为 String 添加扩展函数
fun String.removeSpaces(): String {
    return this.replace(" ", "")
}

// 使用
val text = "Hello World"
val result = text.removeSpaces() // "HelloWorld"

// 为 View 添加扩展函数
fun View.show() {
    this.visibility = View.VISIBLE
}

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

扩展属性

// 扩展属性
val String.lastChar: Char
    get() = this[this.length - 1]

// 使用
val text = "Hello"
val last = text.lastChar // 'o'

数据类

数据类定义

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

// 使用
val user = User(1, "John", "john@example.com")
println(user) // User(id=1, name=John, email=john@example.com)

// 复制
val user2 = user.copy(name = "Jane")

// 解构
val (id, name, email) = user

数据类限制

// 数据类限制
// 1. 主构造函数至少有一个参数
// 2. 主构造函数参数必须标记为 val 或 var
// 3. 数据类不能是抽象、开放、密封或内部类

密封类

密封类定义

// 密封类:限制子类只能在同一个文件中
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val message: String) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

// 使用
fun handleResult(result: Result<String>) {
    when (result) {
        is Result.Success -> println(result.data)
        is Result.Error -> println(result.message)
        is Result.Loading -> println("Loading...")
    }
}

协程基础

协程创建

// 启动协程
GlobalScope.launch {
    delay(1000)
    println("Hello from coroutine")
}

// 使用 runBlocking
runBlocking {
    delay(1000)
    println("Hello")
}

// 使用 CoroutineScope
val scope = CoroutineScope(Dispatchers.Main)
scope.launch {
    delay(1000)
    println("Hello")
}

协程作用域

// CoroutineScope
class MyActivity : AppCompatActivity(), CoroutineScope by MainScope() {
    override fun onDestroy() {
        cancel() // 取消所有协程
        super.onDestroy()
    }
}

// viewModelScopeViewModel
class MyViewModel : ViewModel() {
    fun loadData() {
        viewModelScope.launch {
            // 协程代码
        }
    }
}

// lifecycleScopeLifecycleOwner
lifecycleScope.launch {
    // 协程代码
}

协程上下文

// Dispatchers
launch(Dispatchers.Main) {
    // 主线程
}

launch(Dispatchers.IO) {
    // IO 线程
}

launch(Dispatchers.Default) {
    // 默认线程池
}

委托

类委托

// 类委托:将接口实现委托给另一个对象
interface Base {
    fun print()
}

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

class Derived(b: Base) : Base by b

// 使用
val b = BaseImpl(10)
val derived = Derived(b)
derived.print() // 10

属性委托

// lazy 委托:延迟初始化
val lazyValue: String by lazy {
    println("Computed!")
    "Hello"
}

// 使用
println(lazyValue) // 第一次访问时计算
println(lazyValue) // 直接返回缓存值

// observable 委托:监听属性变化
var name: String by Delegates.observable("Initial") { prop, old, new ->
    println("$old -> $new")
}

高阶函数

高阶函数定义

// 高阶函数:接受函数作为参数或返回函数
fun operation(x: Int, y: Int, op: (Int, Int) -> Int): Int {
    return op(x, y)
}

// 使用
val result = operation(5, 3) { a, b -> a + b } // 8
val result2 = operation(5, 3) { a, b -> a * b } // 15

常用高阶函数

val list = listOf(1, 2, 3, 4, 5)

// map转换
val doubled = list.map { it * 2 } // [2, 4, 6, 8, 10]

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

// reduce累积
val sum = list.reduce { acc, i -> acc + i } // 15

// forEach遍历
list.forEach { println(it) }

Lambda表达式

Lambda 语法

// Lambda 表达式
val sum = { x: Int, y: Int -> x + y }
println(sum(1, 2)) // 3

// 简化语法
val list = listOf(1, 2, 3)
list.forEach { println(it) }

// it单个参数的隐式名称
list.map { it * 2 }

Lambda 与集合

val numbers = listOf(1, 2, 3, 4, 5)

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

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

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

// any / all
val hasEven = numbers.any { it % 2 == 0 } // true
val allEven = numbers.all { it % 2 == 0 } // false

面试常见问题

Q1: Kotlin 和 Java 的区别?

答案:

  1. 空安全Kotlin 有可空类型,编译时检查
  2. 简洁性Kotlin 代码更简洁
  3. 扩展函数:可以为类添加新方法
  4. 数据类:自动生成常用方法
  5. 协程:轻量级线程

Q2: Kotlin 空安全机制?

答案:

  • 可空类型:String? 表示可能为 null
  • 安全调用:?. 操作符
  • Elvis 操作符:?: 提供默认值
  • 非空断言:!! 强制非空

Q3: 扩展函数的作用?

答案:

  • 为现有类添加新方法
  • 不修改原类代码
  • 提高代码复用性
  • 使代码更易读

Q4: 数据类的特点?

答案:

  • 自动生成 equalshashCodetoStringcopy 方法
  • 支持解构声明
  • 简化数据模型定义

Q5: 协程的优势?

答案:

  1. 轻量级:比线程更轻量
  2. 挂起恢复:可以挂起和恢复
  3. 结构化并发:自动管理生命周期
  4. 简化异步代码

最后更新2024年