流程控制是编程语言的核心能力,它让程序能够根据不同条件执行不同逻辑,或重复执行特定操作。Kotlin 提供了简洁而强大的流程控制语法,在吸收 Java 优点的同时,增加了更多灵活性和表达力。本文将详细讲解 Kotlin 中的流程控制结构,帮助你掌握代码的逻辑分支与循环技巧。
一、if-else 表达式:灵活的条件判断
Kotlin 中的 if-else
不仅是流程控制语句,更是可以返回值的表达式,这比 Java 的 if-else
功能更丰富。
1. 基础用法:条件判断与分支执行
if-else
的基础用法与 Java 类似,用于根据条件执行不同代码块:
Kotlin
fun checkNumber(num: Int) {
if (num > 0) {
println("正数")
} else if (num < 0) {
println("负数")
} else {
println("零")
}
}
- 条件表达式必须返回布尔值(
Boolean
) - 当代码块只有一行时,可省略大括号(但建议保留以提高可读性)
else if
可用于处理多个条件分支else
是可选的,用于处理所有未覆盖的情况
2. 作为表达式返回值:替代 Java 的三元运算符
Kotlin 没有 Java 中的三元运算符(condition ? a : b
),因为 if-else
本身就可以作为表达式返回值:
Kotlin
var a = 20
var b = 25
var score = 80
// 基础用法:给变量赋值
val max = if (a > b) a else b
println(max)
// 复杂用法:代码块中最后一行作为返回值
val result = if (score >= 60) {
println("及格")
true // 此行为返回值
} else {
println("不及格")
false // 此行为返回值
}
这种特性让代码更灵活,尤其适合需要在条件判断中执行额外逻辑的场景。
3. 嵌套 if-else 的优化技巧
过多的嵌套 if-else
会导致代码可读性下降,可采用以下优化技巧:
技巧 1:提前返回减少嵌套
Kotlin
// 优化前:多层嵌套
fun calculatePrice(price: Double, isMember: Boolean, isVIP: Boolean): Double {
if (isMember) {
if (isVIP) {
return price * 0.7
} else {
return price * 0.9
}
} else {
return price
}
}
// 优化后:提前返回
fun calculatePrice(price: Double, isMember: Boolean, isVIP: Boolean): Double {
if (!isMember) return price
if (isVIP) return price * 0.7
return price * 0.9
}
技巧 2:使用逻辑运算符合并条件
Kotlin
// 优化前
if (a > 0) {
if (b < 10) {
// 执行逻辑
}
}
// 优化后
if (a > 0 && b < 10) {
// 执行逻辑
}
技巧 3:复杂场景改用 when 表达式
当条件判断过于复杂时,可考虑使用 when
表达式(下文将详细讲解)。
二、when 表达式:更强大的分支选择
when
表达式是 Kotlin 对 Java switch-case
的增强替代,支持更丰富的匹配模式,且同样可以作为表达式返回值。
1. 基础语法:替代 Java 的 switch-case
Kotlin
fun getColorName(colorCode: Int): String {
return when (colorCode) {
1 -> "红色"
2 -> "绿色"
3 -> "蓝色"
else -> "未知颜色"
}
}
与 Java switch
的区别:
- 不需要显式添加
break
,默认自动跳出 - 支持任意类型匹配(不仅是整数)
- 必须覆盖所有可能情况(或使用
else
兜底) - 可作为表达式返回值
2. 匹配常量(数值、字符串、字符)
when
支持匹配各种常量类型:
Kotlin
fun handleCommand(command: String) {
when (command) {
"start" -> println("启动程序")
"stop" -> println("停止程序")
"restart" -> println("重启程序")
else -> println("未知命令: $command")
}
}
fun checkChar(c: Char) {
when (c) {
'a', 'e', 'i', 'o', 'u' -> println("元音字母")
in '0'..'9' -> println("数字字符")
else -> println("其他字符")
}
}
注意:多个常量可放在同一分支,用逗号分隔。
3. 匹配范围(in 关键字)
使用 in
关键字可匹配范围,配合 ..
区间运算符使用:
Kotlin
fun getGrade(score: Int): Char {
return when (score) {
in 90..100 -> 'A'
in 80 until 90 -> 'B' // until 表示半开区间 [80,90)
in 60 until 80 -> 'C'
in 0 until 60 -> 'D'
else -> '?'
}
}
in
还可用于检查是否在集合中:
Kotlin
fun isValidOperator(op: String): Boolean {
return when (op) {
in setOf("+", "-", "*", "/") -> true
else -> false
}
}
4. 匹配类型(is 关键字)
使用 is
关键字可进行类型判断,且会自动完成类型转换(智能转换):
Kotlin
fun handleData(data: Any) {
when (data) {
is String -> println("字符串长度: ${data.length}") // 自动转换为 String
is Int -> println("整数的平方: ${data * data}") // 自动转换为 Int
is Boolean -> println("布尔值: $data")
else -> println("未知类型: ${data.javaClass.name}")
}
}
这比 Java 的 instanceof
更简洁,无需显式类型转换。
5. 作为表达式使用
when
作为表达式时,符合条件的分支值即为返回值:
Kotlin
fun calculate(a: Int, b: Int, op: String): Int {
return when (op) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> if (b != 0) a / b else 0
else -> throw IllegalArgumentException("不支持的运算符: $op")
}
}
甚至可以不带参数,直接在分支条件中写任意布尔表达式:
Kotlin
fun checkNumber(n: Int): String {
return when {
n > 0 && n % 2 == 0 -> "正偶数"
n > 0 && n % 2 == 1 -> "正奇数"
n < 0 -> "负数"
else -> "零"
}
}
三、for 循环:简洁的迭代方式
Kotlin 的 for
循环主要用于遍历迭代器(如区间、集合、数组等),语法比 Java 更简洁。
1. 遍历区间(.. 运算符、until、step)
Kotlin 提供了直观的区间表示法,配合 for
循环可轻松实现次数控制:
Kotlin
// 闭区间 [1,5]:包含 1 和 5
for (i in 1..5) {
print(i) // 输出:12345
}
// 半开区间 [1,5):包含 1,不包含 5
for (i in 1 until 5) {
print(i) // 输出:1234
}
// 倒序遍历
for (i in 5 downTo 1) {
print(i) // 输出:54321
}
// 指定步长(step)
for (i in 1..10 step 2) {
print(i) // 输出:13579
}
// 倒序+步长
for (i in 10 downTo 2 step 2) {
print(i) // 输出:108642
}
2. 遍历集合(List/Set/Map)
Kotlin 对集合的遍历支持非常友好:
Kotlin
// 遍历 List
val fruits = listOf("苹果", "香蕉", "橙子")
for (fruit in fruits) {
println(fruit)
}
// 遍历 Set
val numbers = setOf(10, 20, 30)
for (num in numbers) {
println(num)
}
// 遍历 Map
val user = mapOf(
"name" to "张三",
"age" to 25,
"gender" to "男"
)
// 方式1:遍历键值对
for ((key, value) in user) {
println("$key: $value")
}
// 方式2:遍历键
for (key in user.keys) {
println("键: $key")
}
// 方式3:遍历值
for (value in user.values) {
println("值: $value")
}
3. 遍历数组
数组遍历与集合类似,还可通过索引遍历:
Kotlin
val arr = arrayOf("a", "b", "c", "d")
// 直接遍历元素
for (item in arr) {
println(item)
}
// 通过索引遍历
for (i in arr.indices) { // indices 返回数组索引范围
println("索引 $i: ${arr[i]}")
}
// 同时获取索引和元素
for ((index, value) in arr.withIndex()) {
println("索引 $index: $value")
}
4. 自定义循环次数与步长
结合区间操作符,可灵活控制循环次数和步长:
Kotlin
// 循环 5 次(0-4)
for (i in 0 until 5) {
println("循环第 ${i+1} 次")
}
// 从 10 循环到 1,步长为 3
for (i in 10 downTo 1 step 3) {
println(i) // 输出:10 7 4 1
}
四、while 与 do-while 循环:条件控制的循环
while
和 do-while
循环适用于需要根据条件重复执行的场景,两者的区别在于执行顺序不同。
1. while 循环:先判断后执行
while
循环先判断条件,只有条件为 true
时才执行循环体:
Kotlin
fun countDown(n: Int) {
var remaining = n
while (remaining > 0) { // 先判断条件
println(remaining)
remaining--
}
println("发射!")
}
// 调用:countDown(3)
// 输出:3 2 1 发射!
如果初始条件就为 false
,循环体一次也不会执行。
2. do-while 循环:先执行后判断
do-while
循环先执行一次循环体,再判断条件,因此至少会执行一次:
Kotlin
fun inputUntilPositive() {
var number: Int
do {
println("请输入一个正数:")
number = readLine()?.toIntOrNull() ?: 0
} while (number <= 0) // 后判断条件
println("你输入了正数:$number")
}
适合需要 "至少执行一次" 的场景,如用户输入验证。
3. 循环终止(break)与跳过(continue)
break
:立即终止当前循环,跳出循环体continue
:跳过当前循环的剩余部分,直接进入下一次循环
Kotlin
// 使用 break 终止循环
for (i in 1..10) {
if (i == 5) break // 当 i=5 时终止循环
print(i) // 输出:1234
}
// 使用 continue 跳过当前迭代
for (i in 1..10) {
if (i % 2 == 0) continue // 偶数时跳过
print(i) // 输出:13579
}
4. 嵌套循环的使用场景
嵌套循环常用于处理多维数据结构(如二维数组)或需要多层迭代的场景:
Kotlin
// 打印 5x5 的乘法表
for (i in 1..5) {
for (j in 1..i) {
print("$j×$i=${i*j} ")
}
println() // 换行
}
// 输出:
// 1×1=1
// 1×2=2 2×2=4
// 1×3=3 2×3=6 3×3=9
// ...
带标签的 break/continue
在嵌套循环中,可通过标签(label@
)控制外层循环:
Kotlin
outer@ for (i in 1..3) {
inner@ for (j in 1..3) {
if (i == 2 && j == 2) {
break@outer // 终止外层循环
// continue@outer // 跳过外层循环的当前迭代
}
print("($i,$j) ")
}
println()
}
输出(使用 break@outer
时):
plaintext
(1,1) (1,2) (1,3)
(2,1)
五、流程控制的最佳实践
- 优先使用表达式形式 :
if-else
和when
作为表达式可使代码更简洁 - 减少嵌套层级:过多的嵌套会降低可读性,可通过提前返回、逻辑合并等方式优化
- 合理选择循环类型 :
- 遍历区间 / 集合首选
for
循环 - 条件循环优先考虑
while
- 至少执行一次的场景用
do-while
- 遍历区间 / 集合首选
- 避免死循环 :确保循环条件最终会变为
false
,或提供明确的break
出口 - 复杂条件用 when :多分支判断时,
when
比if-else
链更易读