Kotlin學習筆記(二)循環,跳轉

提示:本文爲作者閱讀Kotlin中文站學習筆記,建議讀者移步Kotlin中文站完整學習。

源文件通常以包聲明開頭,源文件所有內容都包含在聲明的包內,如果沒有聲明包,文件內容屬於無聲明的默認包。當我們創建一個Kotlin文件時,Android studio會幫我們在文件頂部自動聲明包。

package com.gyg.kolin

Kotlin會默認導入一些包到文件中,除了默認導入的包,開發者也需要導入自己的包,可以單獨導入包下的某一個內容,也可以導入包下的所有內容。當命名衝突時,可以通過as關鍵字在本地重命名來消除歧義。

import foo.Bar//導入foo包下的Bar
import foo.*//導入foo包下的所有內容
import foo.Bar as Bar2//導入foo包下的額Bar,並且本地重命名爲Bar2

控制流

if表達式

在Kotlin中,if是一個表達式,它可以返回一個值。

val a:Int=23
val b:Int=46
val max:Int
max=if(a>b) a else b//if作爲一個表達式,當a>b時返回值a,否則返回值b

if的分支也可以是一個代碼塊,最後的表達式爲該塊的值

val a:Int=23
val b:Int=46
val max:Int
max=if(a>b){
    print("max="+a)
    a
}else{
    print("max="+b)
    b
}

注意:如果if作爲一個表達式使用,除非編譯器能夠檢測出所有的可能情況都已經覆蓋了,否則必須有else分支。

我們也可以像Java中一樣,把if作爲一個語句使用

val a:Int=23
val b:Int=46
val max:Int
if(a>b){
    max=a
}else{
    max=b
}

when表達式

when表達式,與Java中的switch語句類似。when 將它的參數和所有的分支條件順序比較,直到某個分支滿足條件。它可以被當作表達式使用, 符合條件的分支的值就是整個表達式的值。(像 if 一樣,每一個分支可以是一個代碼塊,它的值是塊中最後的表達式的值。)例如:

val a: Int = 3
    val b: Int = 5
    var max: Int
    max = when (a > b) {
        true -> {
            print("max=a")
            a
        }
        false -> {
            print("max=b")
            b
        }
        else -> {
            print("a=b")
            a
        }
    }

也可以當做語句使用, 忽略個別分支的值。

val a:Int=3
    val b:Int=5
    var max:Int
    when(a>b){
        true->{
            print("max=a")
            max=a
        }
        false->{
            print("max=b")
            max=b
        }
        else->{
            print("a=b")
            max=a
        }
    }

如果其他分支都不滿足條件將會求值 else 分支。 如果 when 作爲一個表達式使用,則必須有 else 分支, 除非編譯器能夠檢測出所有的可能情況都已經覆蓋了。

如果很多分支需要用相同的方式處理,則可以把多個分支條件放在一起,用逗號分隔:

var x:Int=0
    when(x){
        0,1-> print("x==1或x==2")
        else-> print("otherwise")
    }

我們可以用任意表達式(而不只是常量)作爲分支條件

when (x) {
    parseInt(s) -> print("s encodes x")
    else -> print("s does not encode x")
}

我們也可以檢測一個值在(in)或者不在(!in)一個區間或者集合中:

val x:Int=5
    val values:IntArray= intArrayOf(0,5,7,9)
    when(x){
        in 0..10->{//區間
            print("x is in 0..10")
        }
        in values->{//集合
            print("x is in values")
        }
    }

另一種可能性是檢測一個值是(is)或者不是(!is)一個特定類型的值。注意: 由於智能轉換,你可以訪問該類型的方法和屬性而無需任何額外的檢測。

fun getType(value:Any):Unit{
        when(value){
            is String-> print("value is a String type")
            is Int-> print("value is Int type")
            else-> print("value is not a String type or Int type")
        }
    }

如果不提供參數,所有的分支條件都是簡單的布爾表達式,而當一個分支的條件爲真時則執行該分支:

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

For循環

for循環可以對任何提供迭代器(iterator)的對象進行遍歷,即這個對象:

  • 有一個成員函數或者擴展函數iterator(),它的返回類型

    • 有一個成員函數或擴展函數next(),返回這個對象的成員元素。並且
    • 有一個成員函數或者擴展函數hasNext()返回Boolean。

    這三個函數都要標記爲operator。

val str:String="Hello world"
    for (item in str) print(item)

對數組的 for 循環會被編譯爲並不創建迭代器的基於索引的循環。
如果你想要通過索引遍歷一個數組或者一個 list,你可以這麼做:

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

注意這種“在區間上遍歷”會編譯成優化的實現而不會創建額外對象。
或者你可以用庫函數 withIndex:

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

While循環

我們可以以在Java中的相同姿勢來在Kotlin中使用while循環和do..while循環。

while (x > 0) {
    x--
}

do {
  val y = retrieveData()
} while (y != null) // y 在此處可見

返回和跳轉

Kotlin有三種結構化跳轉表達式:

  • return 默認從直接包圍它的函數或者匿名函數返回。
  • break 默認終止最直接包圍它的循環.
  • continue 默認繼續下一次最直接包圍它的循環。

這些表達式的類型都是Nothing類型。
所有這些表達式可以作爲包含它的更大表達式的一部分:

val name=person.name?:return

Break,Continue標籤

Kotlin中,我們可以用標籤來標記一個表達式,標籤的格式爲:標籤字符後跟@符號,例如:abc@,foreach@等等。要爲一個表達式加標籤,我們只要在其前加標籤即可。

abc@ for (item in str) print(item)

我們可以用標籤來限制break和continue表達式:

outer@for (i in 0..10){
        innrer@for (j in 0..10){
            if (i==3&&j==3)continue@outer
            if (i==5&&j==5) break@outer
        }
    }

標籤限制的break跳轉到更好位於該標籤指定的循環後面的執行點,continue繼續標籤指定的循環的下一次循環。

標籤處返回

Kotlin中,return語句是從最直接包含它的fun標記的函數中返回,例如下面這樣:

fun foo() {
    ints.forEach {
        if (it == 0) return
        print(it)
    }
}

ruturn 直接從foo()函數中返回,如果我們要從lambda表達式中返回,必須給它加標籤並用以限制return表達式:

fun foo() {
    ints.forEach @lambda{
        if (it == 0) return@lambda
        print(it)
    }
}

這樣,return就會從lambda函數中返回。或者更方便的,我們可以使用隱式標籤,它與接受該lambda表達式的函數同名:

fun foo() {
    ints.forEach {
        if (it == 0) return@forEach
        print(it)
    }
}

或者,我們用匿名函數來代替lambda表達式,匿名函數裏的return表達式,將直接從該匿名函數中返回。

fun foo() {
    ints.forEach(fun(value: Int) {
        if (value == 0) return
        print(value)
    })
}

當要返回一個值的時候,解析器優先選用標籤限制的 return,即

return@a 1

意爲“從標籤 @a 返回 1”,而不是“返回一個標籤標註的表達式 (@a 1)”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章