Kotlin: Kotlin基础语法详解
最后更新:2026-08-26
Kotlin 的语法设计哲学:能用表达式就不用语句,能省的代码绝不多写一行。这让 Alice 写出的代码比 Java 短 40% 却表达更多。
1. 你将学到
- vs :不可变优先思维
- 字符串模板与多行字符串
- 表达式的完整形态
- 区间与迭代: / / /
- 表达式体函数与代码习惯
2. 一个开发者的真实故事
(1) 痛点:可变状态引发的并发 Bug
Alice 在 OrderProcessor 中用 定义了共享的订单计数器,在高并发下出现数据竞争,导致计数结果偏差 2%——百万级订单下就是 20,000 笔差异。
(2) 不可变优先的解法
KOTLIN
// BAD: mutable shared state
var orderCount = 0 // Race condition!
// GOOD: immutable + functional pipeline
val processedOrders = orders
.filter { it.status == "CONFIRMED" }
.also { println("Processed ${it.size} orders") }
不可变数据天然线程安全, 是 Kotlin 程序员的第一选择, 是最后手段。
3. val 与 var:不可变优先
(1) 基本语法
KOTLIN
// val: read-only (immutable reference) - PREFERRED
val orderId = "ORD-001" // Type inferred as String
val total: Double = 299.99 // Explicit type
// var: mutable (reassignable) - USE SPARINGLY
var status = "PENDING" // Can be reassigned
status = "CONFIRMED" // OK
// val does NOT mean the object is immutable
val items = mutableListOf`<Order>`() // Reference is val, list is mutable
items.add(Order("ORD-002", 150.0, "NEW")) // OK - modifying the list
// items = mutableListOf() // ERROR - cannot reassign val
(2) val vs var 对比
| 维度 | ||
|---|---|---|
| 重新赋值 | 不允许 | 允许 |
| 线程安全 | 引用不可变,天然安全 | 需同步保护 |
| 推荐度 | 首选 | 最后手段 |
| 类比 | Java | Java 普通变量 |
| 底层 | 只读引用(对象可能可变) | 可变引用 |
4. 字符串模板
(1) 基础模板
KOTLIN
val orderId = "ORD-001"
val total = 299.99
// Simple variable reference
println("Order: $orderId")
// Expression in template
println("Total: \$$total USD")
println("Tax: \$${total * 0.08} USD")
// Arbitrary expression with ${}
val items = listOf("Widget", "Gadget")
println("Item count: ${items.size}, First: ${items[0]}")
(2) 多行字符串(raw string)
KOTLIN
val receipt = """
|Order ID: ORD-001
|Total: $299.99 USD
|Status: CONFIRMED
""".trimMargin()
// Alternative: trimIndent
val json = """
{
"order_id": "ORD-001",
"total": 299.99
}
""".trimIndent()
(3) 字符串模板对比
| 特性 | Java | Kotlin |
|---|---|---|
| 变量引用 | ||
| 表达式 | ||
| 多行 | 无原生支持 | |
| 缩进处理 | 手动 | / |
5. when 表达式
是 的全面升级版——它是表达式,有返回值,能匹配类型、范围和任意条件。
(1) 基础用法
KOTLIN
// when as expression (must be exhaustive)
val status = "CONFIRMED"
val label = when (status) {
"PENDING" -> "Waiting for payment"
"CONFIRMED" -> "Payment received"
"SHIPPED" -> "In transit"
"CANCELLED" -> "Order cancelled"
else -> "Unknown status"
}
(2) 高级匹配
KOTLIN
// Multiple values
when (status) {
"PENDING", "NEW" -> processNewOrder()
in listOf("CONFIRMED", "PAID") -> shipOrder()
else -> handleOther()
}
// Range matching
val quantity = 150
when (quantity) {
in 1..10 -> println("Small order")
in 11..100 -> println("Medium order")
in 101..1_000 -> println("Large order")
else -> println("Bulk order")
}
// Type matching
fun describe(obj: Any): String = when (obj) {
is String -> "String of length ${obj.length}"
is Int -> "Integer: $obj"
is List<*> -> "List with ${obj.size} elements"
else -> "Unknown type"
}
(3) when 分支决策树
flowchart LR
A[when status] --> B["PENDING, NEW"]
A --> C["CONFIRMED, PAID"]
A --> D["SHIPPED"]
A --> E["CANCELLED"]
A --> F[else]
B --> B1[processNewOrder]
C --> C1[shipOrder]
D --> D1[trackShipment]
E --> E1[refundOrder]
F --> F1[handleOther]
(4) when vs switch 对比
| 维度 | Java switch | Kotlin when |
|---|---|---|
| 返回值 | 语句,无返回值 | 表达式,有返回值 |
| 多值匹配 | 需要 case 穿透 | |
| 范围匹配 | 不支持 | |
| 类型匹配 | 不支持 | |
| 守卫条件 | 不支持 | |
| 穷尽检查 | 无 | 编译器强制(表达式模式) |
6. 区间与迭代
(1) 区间操作符
KOTLIN
// Closed range: includes both ends
for (i in 1..5) print("$i ") // 1 2 3 4 5
// Half-open range: excludes end
for (i in 1 until 5) print("$i ") // 1 2 3 4
// Step
for (i in 1..10 step 2) print("$i ") // 1 3 5 7 9
// DownTo
for (i in 5 downTo 1) print("$i ") // 5 4 3 2 1
// Char range
for (c in 'A'..'E') print("$c ") // A B C D E
(2) 集合迭代
KOTLIN
val orders = listOf(
Order("ORD-001", 299.99),
Order("ORD-002", 1_500.00),
Order("ORD-003", 45.50)
)
// Iterate with index
for ((index, order) in orders.withIndex()) {
println("[$index] ${order.id}: \$${order.total} USD")
}
// Iterate map
val statusMap = mapOf("ORD-001" to "SHIPPED", "ORD-002" to "PENDING")
for ((id, status) in statusMap) {
println("$id -> $status")
}
(3) 区间操作符速查
| 操作符 | 含义 | 示例 | 结果 |
|---|---|---|---|
| 闭区间 | 1,2,3,4,5 | ||
| 半开区间 | 1,2,3,4 | ||
| 步长 | 1,4,7,10 | ||
| 递减 | 5,4,3,2,1 | ||
| 包含检查 | true |
7. 表达式体函数与代码习惯
(1) 表达式体函数
KOTLIN
// Block body
fun calculateTax(total: Double): Double {
return total * 0.08
}
// Expression body (more concise)
fun calculateTax(total: Double): Double = total * 0.08
// Type inference with expression body
fun calculateTax(total: Double) = total * 0.08
(2) Kotlin 代码习惯
KOTLIN
// 1. Semicolons are optional
val x = 1 // No semicolon needed
// 2. Trailing lambda convention
orders.filter { it.total > 1_000 } // lambda outside parens
// 3. It keyword for single-parameter lambda
orders.map { it.id } // 'it' = implicit parameter
// 4. String template over concatenation
val msg = "Order $orderId confirmed" // Not "Order " + orderId + " confirmed"
// 5. Expression body for simple functions
fun isHighValue(order: Order) = order.total > 10_000
(3) Java vs Kotlin 习惯对比
| 习惯 | Java | Kotlin |
|---|---|---|
| 分号 | 必须 | 可选 |
| 字符串拼接 | 运算符 | 模板 |
| 简单函数 | 块体 | 表达式体 |
| Lambda 位置 | 参数内 | 尾部括号外 |
| 单参数 Lambda | 命名参数 | 关键字 |
8. 完整示例:OrderProcessor 订单分流
KOTLIN
// ============================================
// OrderProcessor - Order Routing Engine
// Feature: Route orders based on status and value
// ============================================
data class Order(val id: String, val total: Double, val status: String)
fun routeOrder(order: Order): String = when {
order.status == "CANCELLED" -> "REFUND_QUEUE"
order.total > 10_000 -> "VIP_PIPELINE"
order.total > 1_000 -> "PRIORITY_PIPELINE"
order.status == "CONFIRMED" -> "STANDARD_PIPELINE"
order.status in listOf("PENDING", "NEW") -> "WAITING_QUEUE"
else -> "MANUAL_REVIEW"
}
fun processBatch(orders: List`<Order>`) {
for ((index, order) in orders.withIndex()) {
val pipeline = routeOrder(order)
val priority = when (pipeline) {
"VIP_PIPELINE" -> "CRITICAL"
"PRIORITY_PIPELINE" -> "HIGH"
"STANDARD_PIPELINE" -> "NORMAL"
else -> "LOW"
}
println("[${index + 1}] ${order.id} -> $pipeline (Priority: $priority)")
}
}
fun main() {
val orders = listOf(
Order("ORD-001", 299.99, "CONFIRMED"),
Order("ORD-002", 15_000.00, "CONFIRMED"),
Order("ORD-003", 2_500.00, "PENDING"),
Order("ORD-004", 45.50, "CANCELLED"),
Order("ORD-005", 750.00, "NEW")
)
println("=== Order Routing Report ===")
processBatch(orders)
// Summary with functional pipeline
val pipelineCounts = orders
.map { routeOrder(it) }
.groupingBy { it }
.eachCount()
println("\n=== Pipeline Distribution ===")
for ((pipeline, count) in pipelineCounts) {
println(" $pipeline: $count orders")
}
}
输出:
TEXT
📖 仅展示
=== Order Routing Report ===
[1] ORD-001 -> STANDARD_PIPELINE (Priority: NORMAL)
[2] ORD-002 -> VIP_PIPELINE (Priority: CRITICAL)
[3] ORD-003 -> PRIORITY_PIPELINE (Priority: HIGH)
[4] ORD-004 -> REFUND_QUEUE (Priority: LOW)
[5] ORD-005 -> WAITING_QUEUE (Priority: LOW)
=== Pipeline Distribution ===
STANDARD_PIPELINE: 1 orders
VIP_PIPELINE: 1 orders
PRIORITY_PIPELINE: 1 orders
REFUND_QUEUE: 1 orders
WAITING_QUEUE: 1 orders
❓ 常见问题
Q val 定义的集合能修改内容吗?
A 能。val 只保证引用不变,集合内容仍然可以修改。需要真正不可变集合请使用 而非 。
Q when 表达式必须写 else 吗?
A 当 when 作为表达式使用时,编译器要求穷尽所有分支,否则必须写 else。当 when 作为语句使用时,else 可选。
Q 和 一样吗?
A 效果一样,但语义不同。 表示"从 1 到 5(含)", 表示"从 1 到 6 之前"。遍历列表索引时 更常用。
Q 表达式体函数什么时候该用?
A 函数体是单个表达式时用表达式体,超过 2 行逻辑时用块体。可读性是第一原则。
Q 字符串模板中 和 有什么区别?
A 只能引用简单变量名; 可以包含任意表达式,如 或 。
Q when 可以匹配浮点数范围吗?
A 技术上可以,但浮点数精度问题可能导致意外结果。建议用整数范围或显式比较。
▶ 示例:val 与 var
KOTLIN
val name = "Alice" // 不可变
var age = 30 // 可变
age = 31 // OK
// name = "Bob" // 编译错误
输出:
TEXT
📖 仅展示
编译通过;name 重新赋值失败
▶ 示例:when 表达式
KOTLIN
val score = 85
val grade = when {
score >= 90 -> "A"
score >= 80 -> "B"
else -> "C"
}
println(grade)
输出:
TEXT
📖 仅展示
B
▶ 示例:for 循环
KOTLIN
for (i in 1..3) println(i)
for (s in listOf("a", "b")) println(s)
输出:
TEXT
📖 仅展示
1
2
3
a
b
📖 小节
- 优先, 是最后手段——不可变引用天然线程安全
- 字符串模板 / 替代字符串拼接,多行字符串用
- 是表达式的 升级版,支持多值、范围、类型和守卫匹配
- 区间操作符:(闭区间)、(半开)、(步长)、(递减)
- 表达式体函数让简单函数更简洁,可读性是取舍标准
- Kotlin 代码习惯:无分号、尾 Lambda、 关键字、字符串模板
📝 作业
- 基础题(难度⭐):用 和字符串模板编写一个函数,输出订单摘要 。提示:
- 进阶题(难度⭐⭐):用 表达式实现一个折扣计算器:金额 > 10,000 打 8 折,> 5,000 打 9 折,其余不打折。提示: 守卫条件
- 挑战题(难度⭐⭐⭐):用区间和 实现一个税费阶梯计算器,不同收入区间适用不同税率。提示: