04. Kotlin 流程控制、语句和表达式

条件和循环

程序设计中的流程控制有三种结构,即顺序、分支和循环结构。

if 表达式

if 的工作方式和大多数传统语言一样。

  • if [可选搭配 else]
  • if 搭配 else if [可选搭配 else]
  • 以上两种模式的嵌套语句

注意 如果语句组只有一条语句,可以省略大括号。但一般不建议省略。

在 Kotlin,if 是一个表达式: 它返回一个值。Kotlin 中 没有三元运算符 condition ? then : else, 而是使用 if 表达式。

1
fun maxOf(a: Int, b: Int) = if (a > b) a else b

if 表达式的分支可以是块。在这种情况下,最后一个表达式是块的值:

1
2
3
4
5
6
7
val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}

如果使用 if 作为表达式,用于返回其值或将其赋给变量,则 else 分支是必需的

when 表达式

when 提供多分支程序结构。

Kotlin 提供了更灵活和清晰的 when 构造语句,而不是广泛使用的 switch 语句。 它既可以用作语句,也可以用作表达式。

when 中的每个分支不需要添加 break 语句,分支执行完成就会跳出 when 语句。

1
2
3
4
5
6
7
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}

在运行时“表达式”计算结果,会与每个分支中的“分支条件表达式”进行匹配,直到找到一个分支,然后进入该分支的代码块执行,执行完成结束 when 语句。when 结构当做语句时,最后的 else 分支可以省略。另外,如果语句组所在的代码块只有一条语句,可以省略大括号。

Kotlin 中的 when 语句很灵活,上述示例中表达式结果比较是否等于分支条件表达式结果。此外,还可以使用 in 或者 !in 表达式结果是否在一个范围或集合中;可以用 is 或者 !is 表达式结果是否是某一类型的对象。

1
2
3
4
5
val items = setOf("apple", "banana", "kiwifruit")
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}

如果将 else 作为表达式使用,则除非编译器能够证明所有可能的情况都包含了分支条件(例如,使用枚举类条目和密封类子类型) ,否则 else 分支是强制的。

要定义多种情况下的通用行为,请将它们的条件用一个逗号组合在一行中:

1
2
3
4
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}

您还可以检查一个值是否在范围或集合中:

1
2
3
4
5
6
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")
}

另一个选项是检查一个值是否为或 !是一种特殊的类型。注意,由于智能强制转换,您可以访问该类型的方法和属性,而不需要进行任何额外的检查。

1
2
3
4
fun hasPrefix(x: Any) = when(x) {
is String -> x.startsWith("prefix")
else -> false
}

如果没有提供参数,则分支条件只是布尔表达式。

1
2
3
4
5
when {
x.isOdd() -> print("x is odd")
y.isEven() -> print("y is even")
else -> print("x+y is odd")
}

可以使用以下语法捕获变量中的 subject:

1
2
3
4
5
fun Request.getBody() =
when (val response = executeRequest()) {
is Success -> response.body
is HttpError -> throw HttpException(response.status)
}

循环结构

Kotlin 支持所有常用的循环: for、 while、 do-while。

While 和 do-while 循环在满足条件的情况下连续执行它们的身体。它们之间的区别在于状态检查时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// for 循环
val cakes = listOf("carrot", "cheese", "chocolate")
for (cake in cakes) {
println("Yummy, it's a $cake cake!")
}

// while 循环 和 do-while 循环
var cakesEaten = 0
var cakesBaked = 0
while (cakesEaten < 3) {
println("Eat a Cake")
cakesEaten++
}

do {
println("Bake a Cake")
cakesBaked++
} while (cakesBaked < cakesEaten)

Kotlin 语言中没有 C 语言风格的 for 语句,它的 for 语句相等于 Java 中增强 for 循环语句,只用于对范围、数组或集合进行遍历。

在 for 语句遍历集合时,一般不需要循环变量,但是如果需要使用循环变量,可以使用集合 indices 属性,具体示例代码如下:

1
2
3
4
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}

或者,您可以使用 withIndex 库函数:

1
2
3
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}

迭代器

通过在类中实现 iterator 运算符,可以在类中定义自己的迭代器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Animal(val name: String)

class Zoo(val animals: List<Animal>) {
operator fun iterator(): Iterator<Animal> { // 1
return animals.iterator() // 2
}
}

fun main() {
val zoo = Zoo(listOf(Animal("zebra"), Animal("lion")))
for (animal in zoo) { // 3
println("Watch out, it's a ${animal.name}")
}
}
  1. 定义一个类中的迭代器。它必须被命名为迭代器并且有操作符修饰符。
  2. 返回满足下列方法要求的迭代器:
    next() : Animal
    hasNext () : Boolean
  3. 使用用户定义的迭代器遍历动物园中的动物。

迭代器可以在类型中声明,也可以作为扩展函数声明。

语句

语句关注的代码执行过程。在 Kotlin 语言中,一条语句结束后可以不加分号,也可以加分号,通过情况下绝对不加。但是有一种情况必须加分号,那就是多条语句写在一行的时候,需要通过分号来区别语句(但最后一句可以不加),但一般不建议写在同一行,会影响观感。

1
var a1: Int = 10; var a2: Int = 20;

kotlin 有三个结构跳转表达式:

  • return 默认情况下从最近的封闭函数或匿名函数返回。
  • break 中断结束最近的封闭循环。
  • continue 继续进行到最近的封闭循环的下一步。

break 语句

break 语句可用于 while、do-while 和 for 循环结构,它的作用是强行退出循环体,不再执行循环体中剩余的语句。

在循环体中使用 break 语句有两种方式:带有标签和不带标签。语法格式如下:

1
2
break         //不带标签
break@label //带标签,label 是标签名

continue 语句

continue 语句用来结束本次循环,跳过循环体中尚未执行的语句,接着进行终止条件的判断,以决定是否继续循环。对于for语句,在进行终止条件的判断前,还要先执行迭代语句。

return 语句

表达式

为了使代码更加简洁 Kotlin 将 Java 中一些语句进行简化,使之成为一种表达式,这些表达式包括:控制结构表达式、try 表达式、表达式函数体和对象表达式。

表达式函数

1
2
// 表达式函数体, a + b表达式没有放到一对大括号中
fun sum(a: Int, b: Int): Int = a + b

try 表达式

1
2
3
4
5
6
// try 表达式
val score = try {
} catch (e: Exception) {
return
}
println(score)

参考

第 3 章 第一个 Kotlin 程序-图灵社区