# 流控制
## If 表达式
Kotlin 中的 `if` 是一个表达式,意即它会返回一个值。因此没有三目运算符,因为普通的 `if` 就能很好地担任这个角色。
``` kotlin
// 传统用法
var max = a
if (a < b)
max = b
// 加上 else
var max: Int
if (a > b)
max = a
else
max = b
// 与表达式一样
val max = if (a > b) a else b
```
`if` 分支可以是块,并且一个块中最后的表达式就是值:
``` kotlin
val max = if (a > b) {
print("Choose a")
a
}
else {
print("Choose b")
b
}
```
如果你把 `if` 当成一个表达式而不是指令(例如,返回它的值或把它赋值给一个变量),那么这个表达式必须要有一个 `else` 分支。
查看 [grammar for *if*{: .keyword }](grammar.html#if)
## When 表达式
`when` 代替了类 C 语言中的 switch。最简单的形式类似这样
``` kotlin
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // 注意这个块
print("x is neither 1 nor 2")
}
}
```
`when` 匹配它的所有的参量分支直到一些分支满足条件。`when` 可以作为表达式或指令使用。如果它作为表达式使用,满足的分支的值则成为整个表达式的值。如果作为指令使用,单独分支的值则被忽略(和 `if` 类似,每个分支都可以是一个块,并且值就是最后表达式的值)。
如果其它的分支都没有满足条件则 `else` 分支就会被求值。如果 `when` 作为表达式使用,那么 `else` 是强制的,除非编译器能证明分支条件覆盖了所有的可能性。
如果一些条件应该以同样的方式处理,那么这个分支条件可以以一个逗号合并:
``` kotlin
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
```
我们可以使用任意表达式(不仅仅是常量)作为分支条件
``` kotlin
when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}
```
我们还能检查一个值 `in` 或者 `!in` 在某个[范围](ranges.html)或某个集合内:
``` kotlin
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
```
其它的可能性是要检查一个值 `is` 或 `!is` 某个类型。注意,由于[智能转换](typecasts.html#smart-casts),你不用额外的检查就可以访问这个类型的方法和属性。
```kotlin
val hasPrefix = when(x) {
is String -> x.startsWith("prefix")
else -> false
}
```
`when` 还能作为 `if-else if` 链条的替代。如果没有参量给出,则分支条件就是简单的布尔表达式,并且一个分支是在它的条件为 `true` 时执行:
``` kotlin
when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}
```
查看 [grammar for *when*{: .keyword }](grammar.html#when).
## For 循环
`for` 循环通过提供的迭代器迭代任何东西。语法像下面这样:
``` kotlin
for (item in collection)
print(item)
```
循环体可以是一个块。
``` kotlin
for (item: Int in ints) {
// ...
}
```
就像前面所说的,`for` 通过提供的迭代器迭代任何东西,也就是说:
* 有一个成员或扩展的 `iterator()` 函数所返回的类型
* 有一个成员或扩展的 `next()` 函数,并且
* 有一个成员或扩展的 `hasNext()` 函数返回 `Boolean`。
这三个函数都要标记为 `operator`。
数组上的 `for` 循环被编译成一个基于索引的循环,不会创建一个迭代器对象。
如果你要用一个索引迭代一个数组或一个列表,你可以用这种方法实现:
``` kotlin
for (i in array.indices)
print(array[i])
```
注意“迭代某个范围”会被编译为优化实现,没有额外的对象创建。
另外,你可以使用 `withIndex` 库函数:
``` kotlin
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
```
查看 [grammar for *for*{: .keyword }](grammar.html#for).
## While 循环
*while*{: .keyword } 和 *do*{: .keyword }..*while*{: .keyword } 工作和通常的一样
``` kotlin
while (x > 0) {
x--
}
do {
val y = retrieveData()
} while (y != null) // y 在这里是可见的!
```
查看 [grammar for *while*{: .keyword }](grammar.html#while).
## 循环中的 Break 和 continue
Kotlin 支持循环中传统的 `bread` 和 `continue` 操作符。查看 [Returns and jumps](returns.html)