此篇將介紹 Kotlin 在流程控制相關語法與特性,在 Kotlin 世界中,條件運算式、迴圈使用方式與其他程式語言相似,這邊快速帶大家了解在 Kotlin 中如何操作。
在專案開發中,我們經常會使用到條件判斷來處理邏輯問題,我們可以直接利用下面範例來觀看 Kotlin 在 if..else
的操作,參考如下:
範例是當我們輸入分數(0-100)時,程式會依據所輸入的分數輸出對應的訊息
fun main() {
print("請輸入分數:")
// 宣告 Score 變數並將使用者輸入數值轉為 Int
val score: Int = readLine()!!.toInt()
// 利用 if 判斷輸出對應結果
if (score == 100) { // 當分數為 100 時
println("恭喜考滿分")
} else if (score >= 60) { // 當分數大於 60 時
println("恭喜及格")
} else if (score >= 0) { // 當分數大於 0 且小於 60 時
println("再接再勵")
} else {
println("數值必須介於 0 - 100 之間") // 當數值不是介於 0 - 100 時
}
}
備註:
!!
操作符號為非空斷言(Not-null assertion operator)
,表示我們認為輸入的數值不會是空值,若為空值則會立即出現錯誤狀況,而假如我們不使用!!
操作符號時,Intellij 編輯器會告訴我們轉型會有錯誤,可參考下圖實際狀況:
而與其他語言相比,Kotlin 比較特別的是條件判斷式可根據條件同時進行變數賦值,我們將上面範例改為以下程式:
此範例我們改變上面範例,使用判斷式賦值方法將分數所對應的回應字串回傳給 output
變數,再印出結果
fun main() {
print("請輸入分數:")
// 宣告 score 變數並將使用者輸入數值轉為 Int
val score: Int = readLine()!!.toInt()
// 宣告 output 變數儲存分數對應的回應字串
val output: String =
if (score == 100) // 當分數為 100 時
"恭喜考滿分"
else if (score >= 60) // 當分數大於 60 時
"恭喜及格"
else if (score >= 0) // 當分數大於 0 且小於 60 時
"再接再勵"
else // 當數值不是介於 0 - 100 時
"成績輸入錯誤"
println(output)
}
Kotlin 與其他程式語言比較不同的還有 when
運算式, 在 Kotlin 中,沒有提供其他語言常見的 switch
表達式,而是提供 when
表達式,when
是 Kotlin 的另一個控制流程語法,允許開發者編寫條件式,當滿足某個條件時執行對應程式碼,語法上非常簡潔,條件與執行程式用 →
箭頭符號語法進行配對,此方法適合三到四個流程情況使用,範例如下:
此範例先定義一個 score
變數,再利用 when
表達式進行分數判斷,再回傳對應的訊息,此部份記得此表達式與傳統 switch
不同,when
在條件結束時不需要加上 break
fun main() {
print("請輸入分數:")
// 宣告 score 變數並將使用者輸入數值轉為 Int
val score: Int = readLine()!!.toInt()
// 宣告 comment 變數並將分數對應的回應字串儲存
val comment: String = when (score) {
100 -> "恭喜滿分"
in 60..99 -> "恭喜及格"
in 0..60 -> "再接再勵"
else -> "分數輸入錯誤"
}
println(comment)
}
when
也可以同時多條件判斷,我們試著將上面範例修改為以下:
fun main() {
print("請輸入分數:")
// 宣告 score 變數並將使用者輸入數值轉為 Int
val score: Int = readLine()!!.toInt()
val comment: String = when (score) {
100 -> "恭喜滿分"
in 60..99 -> {
if (score > 80) {
"表現優良"
} else {
"恭喜及格"
}
}
in 0..60 -> "再接再勵"
else -> "分數輸入錯誤"
}
println(comment)
}
Kotlin 還有提供一個簡潔的語法-Elvis
,在實務開發中,我們經常會遇到需要判斷該變數目前是否為 null
的情況,若為 null
,則有預設值進行替代或拋出錯誤提醒,原先情況我們可能會如下範例進行撰寫:
fun main() {
val username: String? = "Devin"
val usernameLength: Int =
if (username == null) {
0
} else {
username.length
}
println(usernameLength) // 輸出 username 字元長度 5
}
而 Kotlin 提供 elvis
語法,可以簡單處理這種情況:
fun main() {
// 若為空,則回傳 0
val username: String? = null
val usernameLength: Int = username?.length ?: 0
println(usernameLength) // 輸出 0
// 拋出錯誤
val password: String? = null
val passwordLength: Int = password?.length ?: throw IllegalArgumentException("資料為 null")
println(passwordLength) // 輸出 Exception in thread "main" java.lang.IllegalArgumentException: 資料為 null
}
使用 ?:
即可檢查對應的值是否為 null
,若為否,則回傳右邊的數值,此數值若開發者不想賦予任何值,也可以使用 return
回傳
val username: String? = "Devin"
val usernameLength: Int = username?.length ?: return
println(usernameLength) // 此行不會執行
迴圈是程式依據設定的條件進行重複工作,當條件為真就持續進行,反之就結束,而 Kotlin 在迴圈方法上提供與Java 相同,都有 for
、while
、 do while
等方法,其中 Kotlin 迴圈操作的方式非常像 Python,如下範例所示 - 利用 for
迴圈將集合內所有元素逐步印出:
// 使用 for in 迴圈
val names = listOf("Anne", "Peter", "Jeff")
for (name in names) {
println(name)
}
// 使用 while 迴圈
val number = 0
while (number < 10) {
println(number)
number++
}
// 使用 do...while 迴圈
val doorPassword = "20200913"
var keyInAmount= 0
do {
println("請輸入密碼進門")
val password = readLine()!! // 轉換 nullable to non-nullable
keyInAmount++
} while (password != doorPassword && keyInAmount < 3)
Kotlin 也提供 Ranges
表達式可讓開發者快速建立兩個值的區間,一般通常會與in
、in!
一起使用,其餘操作如下說明與實作範例,建議閱讀朋友可以直接:
..
操作符號表示為數值區間,例如 x..y
即為數值範圍在 x
與 y
區間until
類似 ..
操作符號,差別在於最後的數值會是目標值 -1
,例如 1 until 3
會印出「1 2」rangeTo
與 ..
屬於相同效果downTo
表示為反向區間,例如 x downTo y
即為 x
遞減到 y
step
為指定區間遞增或遞減值,例如 x .. y step 2
即為 x
每次遞增 2
到目標值 y
fun main() {
// 建立1-4區間數值
for (i in 1..4) print(i) // 此段會印出「1 2 3 4」
// rangeTo 與 .. 屬於相同效果
for (i in 1.rangeTo(4)) println(i) //此段會印出「1 2 3 4」
// until 與 .. 類似相同效果,差別在最終值會-1,
for (i in 1 until 4) println(i) // 此段會印出「1 2 3」
// downTo 為反向區間使用
for (i in 4 downTo 1) print(i) // 此段會印出「4 3 2 1」
// last方法會只輸出區間最後一個值,若要輸出第一個值,可以使用 first 方法
println((1..12 step 2).last) // 此段會印出「11」
// 組合 downTo 與 step 方法
for (i in 8 downTo 5 step 2) print(i) // 此段會印出「8 6」
// 區間也可以使用字母
for (i in 'a' .. 'd') println(i) // 此段會印出「a b c d」
}
在其他程式語言中,我們常會看見迴圈可以搭配 break
與 continue
方法, break
可讓當前迴圈直接整個結束,continue
則是可讓迴圈結束單次運行,而在 Kotlin 可以為迴圈指定名稱,當我們今天運用巢狀迴圈時,可指定要讓哪一個迴圈結束,如下範例:
迴圈在 item1
為 1 與 item2
為 0 時,結束外層單次中斷
fun main() {
// 命名外層迴圈為名稱「a」
a@for(item1 in 0 until 3){
// 命名內層迴圈為名稱「b」
b@for(item2 in 0 until 3){
// 當符合條件時結束外層(a)迴圈跳過此次運行
if(item1 == 1 && item2 == 0){
continue@a
}
println("$element1 => $element2")
}
}
}
// 印出結果為
// 0 => 0
// 0 => 1
// 0 => 2
// 2 => 0
// 2 => 1
// 2 => 2
迴圈在 item1
為 1 與 item2
為 1 時,結束外層迴圈
fun main() {
// 命名外層迴圈為名稱「a」
a@for(item1 in 0 until 3){
// 命名內層迴圈為名稱「b」
b@for(item2 in 0 until 3){
println("$element => $element1")
// 當符合條件時結束整個外層(a)迴圈
if(item1 == 1 && item2 == 1){
break@a
}
}
}
}
// 印出結果為
// 0 => 0
// 0 => 1
// 0 => 2
// 1 => 0
// 1 => 1