首页 Kotlin学习笔记(2) - 控制流程
文章
取消

Kotlin学习笔记(2) - 控制流程

一、条件与循环

1. If表达式

Kotlin中没有三元表达式,if表达式直接可以返回条件分支中的具体值,分支中可以是一个代码块,也可以是具体值,也可以是具体逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var max = a

max = if (a > b) {
    print("Choose a")
    a
} else {
    print("Choose b")
    b
}

max = if (a > b) a else b

if (a > b) {
    max = a
} else {
    max = b
}

2. When表达式

类似于Java中的Switch表达式,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")
    }
}

在多种情况的存在共同行为时,可以用逗号将多条件组合在一起

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

When的条件可以是任何表达式,不仅仅是常量

1
2
3
4
5
6
7
8
when (x) {
    s.toInt() -> print("s encodes 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")
  	is String -> x.startsWith("prefix")
    else -> print("s does not encode x")
}

也可以同过 isor !is函数来检查类型

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

3. For循环

Kotlin中可以进行forech迭代

1
for (item in collection) print(item)

通过指定范围来迭代

1
2
3
4
5
6
for (i in 1..3) {
    println(i)
}
for (i in 6 downTo 0 step 2) {
    println(i)
}

数组或集合可以通过索引来遍历

1
2
3
4
5
6
7
8
9
val array = arrayOf("a", "b", "c")

for (i in array.indices) {
    println(array[i])
}

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

4. While循环

可以直接使用whiledo-while

1
2
3
4
5
6
7
while (x > 0) {
    x--
}

do {
    val y = retrieveData()
} while (y != null) // y is visible here!
  • while:满足条件则执行方法提
  • do-while:至少会执行一次方法体,然后检查条件重复执行

二、返回与跳转

Kotlin提供了三种跳转表达式

  • return:从最近的封闭函数或匿名函数返回
  • break:终止与当前方法体最近的循环
  • continue:继续执行与当前方法体最近的下一次循环

1. 中断、继续循环

Kotlin中break只能够终止当前方法体的当次操作,无法直接打断整个循环,需要使用@标识的标签来进行打断

1
2
3
4
5
6
loop@ for (i in 1..100) {
    for (j in 1..100) {
        if (...) break@loop
      // if(...) continue
    }
}

注意嵌套函数中lambda表达式的return

以下会直接对方法体进行返回

1
2
3
4
5
6
7
8
9
10
11
12
13
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return // non-local return directly to the caller of foo()
        print(it)
    }
    println("this point is unreachable")
}

fun main() {
    foo()
}

//print 12

如果想从lambda表达式中返回的话可以使用标签进行标记

1
2
3
4
5
6
7
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit // local return to the caller of the lambda - the forEach loop
        print(it)
    }
    print(" done with explicit label")
}

通常可以直接使用隐式标签,该标签与lambad表达式的函数同名

1
2
3
4
5
6
7
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach {
        if (it == 3) return@forEach // 局部返回到该 lambda 表达式的调用者——forEach 循环
        print(it)
    }
    print(" done with implicit label")
}

或者也可以使用匿名函数来替代lambda表达式

1
2
3
4
5
6
7
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
        if (value == 3) return  // local return to the caller of the anonymous function - the forEach loop
        print(value)
    })
    print(" done with anonymous function")
}

前面的局部return其实性质类似于java 中的continue,如果想终止单层循环的话我们也可以增加一层嵌套的lambda表达式

1
2
3
4
5
6
7
8
9
fun foo() {
    run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop // non-local return from the lambda passed to run
            print(it)
        }
    }
    print(" done with nested loop")
}

三、异常处理

异常处理由trycatchfinally组成 catch 可以有多个,finally 可以省略,但 catch 与 finally 至少需要一个

1
2
3
4
5
6
7
try {
    // 一些代码
} catch (e: SomeException) {
    // 处理程序
} finally {
    // 可选的 finally 块
}

try是一个表达式,可以有一个返回值,try与catch的返回值是代码体中最后一个表达式,finally中的内容不影响表达式的结果

1
val a: Int? = try { input.toInt() } catch (e: NumberFormatException) { null }

Kotlin中throw是表达式,可以做为Elvis表达式的一部分

1
val s = person.name ?: throw IllegalArgumentException("Name required")
本文由作者按照 CC BY 4.0 进行授权

Kotlin学习笔记(1) - 基础类型

Kotlin学习笔记(3) - 类