Kotlin 实战指南
kotlin fun main() { println("Hello, Kotlin!") }
点击左侧绿色运行按钮,控制台将输出 `Hello, Kotlin!`。
---
## 基本语法
### 变量与类型推断
Kotlin 使用 `val` 声明只读变量(类似 Java 的 `final`),`var` 声明可变变量。
```kotlin
val name = "Alice" // 类型自动推断为 String
var age = 25 // 类型为 Int
// name = "Bob" // 编译错误,val 不可重新赋值
age = 26 // 正确
也可以显式指定类型:
val greeting: String = "Hello"
val count: Int = 10
基本数据类型
Kotlin 中一切皆对象,没有原始类型(但编译后会优化为 JVM 原始类型)。
| 类型 | 示例 |
|---|---|
| Int | 42 |
| Long | 42L |
| Double | 3.14 |
| Float | 3.14f |
| Char | 'A' |
| String | "Kotlin" |
| Boolean | true / false |
字符串模板让变量的嵌入非常方便:
val name = "Kotlin"
println("Hello, $name!") // 输出 Hello, Kotlin!
println("Result: ${1 + 2}") // 表达式需要用大括号
控制流
if 表达式
与许多语言不同,if 是表达式,可以直接返回值:
val max = if (a > b) a else b
when 表达式
取代 Java 的 switch,功能更强大:
when (x) {
1 -> println("x is 1")
2, 3 -> println("x is 2 or 3")
in 4..10 -> println("x is in range")
is Int -> println("x is int")
else -> println("unknown")
}
循环
for 循环可以直接遍历任何可迭代对象:
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
// 遍历区间
for (i in 1..5) {
println(i)
}
// 带步长
for (i in 6 downTo 1 step 2) {
println(i) // 6,4,2
}
函数定义
使用 fun 关键字,参数格式为 name: Type,返回类型写在后面:
fun sum(a: Int, b: Int): Int {
return a + b
}
当函数体是单个表达式时,可简写为:
fun sum(a: Int, b: Int) = a + b
默认参数和具名参数
fun greet(name: String = "Guest", greeting: String = "Hello") {
println("$greeting, $name")
}
greet() // Hello, Guest
greet("Tom") // Hello, Tom
greet(greeting = "Hi") // Hi, Guest
greet("Tom", "Welcome") // Welcome, Tom
高阶函数与 Lambda
Kotlin 支持将函数作为参数或返回值:
fun <T> List<T>.customFilter(predicate: (T) -> Boolean): List<T> {
val result = mutableListOf<T>()
for (item in this) {
if (predicate(item)) result.add(item)
}
return result
}
val numbers = listOf(1, 2, 3, 4, 5)
val even = numbers.customFilter { it % 2 == 0 }
println(even) // [2, 4]
空安全
Kotlin 的类型系统防止 null 滥用。
普通类型不可为 null:
var name: String = "Bob"
// name = null // 编译错误
若要允许 null,使用 ?:
var nullableName: String? = "Alice"
nullableName = null // 正确
安全调用 ?. 会在对象为 null 时返回 null 而不是抛出异常:
val length = nullableName?.length // 若 nullableName 为 null,则 length 为 null
Elvis 操作符 ?: 提供默认值:
val len = nullableName?.length ?: 0
强制调用 !! 断言非空(不推荐,除非确定不为空):
val forced = nullableName!!.length // 若 null 则抛出异常
面向对象
类与继承
Kotlin 中类默认是 public final 的(不可继承),想要可继承需要用 open 修饰。
open class Animal(val name: String) {
open fun sound() = "Animal sound"
}
class Dog(name: String, val breed: String) : Animal(name) {
override fun sound() = "Woof!"
}
属性与访问器
属性可以直接在构造函数中声明,自动生成 getter/setter。
class Person {
var age: Int = 0
set(value) {
if (value >= 0) field = value
}
val isAdult: Boolean
get() = age >= 18
}
数据类
专用于保存数据的类,自动生成 equals(), hashCode(), toString(), copy() 等。
data class User(val id: Int, val name: String)
val user1 = User(1, "Alice")
println(user1) // User(id=1, name=Alice)
val user2 = user1.copy(name = "Bob")
伴生对象与单例
通过 companion object 实现类似静态成员:
class MyClass {
companion object {
const val TAG = "MyClass"
fun create() = MyClass()
}
}
val instance = MyClass.create()
直接使用 object 关键字声明单例:
object Config {
val baseUrl = "https://api.example.com"
}
扩展函数
在不修改原始类的情况下为其添加新函数:
fun String.removeFirstLast(): String =
this.substring(1, this.length - 1)
println("Hello".removeFirstLast()) // ell
集合与函数式编程
Kotlin 标准库为集合提供了丰富的函数式操作,包括 filter, map, flatMap, groupBy 等。
val names = listOf("Alice", "Bob", "Charlie", "David")
// 过滤并转换
val result = names
.filter { it.length > 3 }
.map { it.uppercase() }
println(result) // [ALICE, CHARLIE]
使用序列优化链式操作(惰性求值):
val largeList = (1..1_000_000).toList()
val evenDoubled = largeList.asSequence()
.filter { it % 2 == 0 }
.map { it * 2 }
.take(10)
.toList()
常用集合类型
- List: 有序,可重复,
listOf("a","b") - Set: 无序,不重复,
setOf(1,2,3) - Map: 键值对,
mapOf("key" to "value")
可变版本:mutableListOf, mutableSetOf, mutableMapOf
协程入门
Kotlin 协程提供了一种更简洁的方式处理异步任务,不阻塞线程。
添加依赖
在 build.gradle.kts 中添加:
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
}
启动协程
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(1000L)
println("World!")
}
println("Hello,")
// 输出: Hello, 等 1 秒后打印 World!
}
结构化并发
协程作用域确保子协程的完成:
suspend fun fetchUser(): String {
delay(500) // 模拟网络请求
return "User"
}
fun main() = runBlocking {
val user = async { fetchUser() }
println("Result: ${user.await()}")
}
实战:并发请求
suspend fun fetchData(id: Int): String {
delay(1000) // 模拟耗时
return "Data-$id"
}
fun main() = runBlocking {
val deferreds = (1..5).map { async { fetchData(it) } }
val results = deferreds.awaitAll()
println(results)
}
实战:构建一个简单的命令行待办事项应用
接下来,我们将综合运用上述知识,创建一个命令行待办事项管理器。
需求
- 添加任务
- 列出所有任务
- 标记任务完成
- 退出
代码实现
import java.util.*
data class Task(
val id: UUID = UUID.randomUUID(),
val title: String,
var isCompleted: Boolean = false
)
object TaskManager {
private val tasks = mutableListOf<Task>()
fun add(title: String) {
tasks.add(Task(title = title))
}
fun list() {
tasks.forEachIndexed { index, task ->
val status = if (task.isCompleted) "[x]" else "[ ]"
println("${index + 1}. $status ${task.title}")
}
}
fun complete(index: Int) {
if (index in 1..tasks.size) {
tasks[index - 1].isCompleted = true
} else {
println("Invalid task number.")
}
}
}
fun main() {
val scanner = Scanner(System.`in`)
while (true) {
println("\n--- TODO ---")
println("1. Add Task")
println("2. List Tasks")
println("3. Complete Task")
println("4. Exit")
print("Choose: ")
when (scanner.nextLine()) {
"1" -> {
print("Enter task: ")
val title = scanner.nextLine()
TaskManager.add(title)
}
"2" -> TaskManager.list()
"3" -> {
print("Enter task number to complete: ")
val num = scanner.nextLine().toIntOrNull()
if (num != null) TaskManager.complete(num)
else println("Invalid input.")
}
"4" -> return
else -> println("Invalid choice.")
}
}
}