Kotlin編程學習記錄2

Kotlin編程學習記錄2——條件與循環

條件語句:ifwhen

? Kotlin 的控制流把“表達式優先”作為設計原則——ifwhen 不只是控制語句,都可以作為表達式使用并返回值,這影響了日常代碼風格(更函數式、可組合)。筆者這里影響深刻的是If的可返回表達式性,這個我在GNU C擴展語法中玩過,沒想到在Kotlin中是一個非常標準的用法。

總體要點(速覽)

  • if 可以用作表達式或語句:表達式時可直接返回值(因此 Kotlin 沒有三元運算符)。
  • when 是比 switch 更強大的多分支構造:支持匹配常量、區間、類型檢查、任意條件(無 subject 的 when),也能作為表達式返回值。when 分支不會“穿透”(不需要 break)。
  • when 用于 sealed class(或 sealed interface)時,編譯器可以檢測是否覆蓋所有子類型,從而允許省略 else(exhaustive)。

if:聲明、表達式、注意點

Kotlin的If跟大部分編程語言別無二致,我這種C++er看了都覺得回了家一般。
if (condition) {// statement block
} else {// statement block
}

? 但是獨特的是,當 if 用作表達式時,可以把值直接賦給變量或作為函數返回值:

val max = if (a > b) a else b    // 表達式形式
fun maxOf(a: Int, b: Int) = if (a > b) a else b

說明:Kotlin 因為有 if 表達式,所以沒有三元運算符 ?:

? 這就有點像:

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

? 但是你可以看到寫法上Kotlin使用If直接返回值的寫法顯然簡單的多。

表達式的類型規則

作為表達式時,if 的每個分支末尾表達式會被推斷為某個類型。整個 if 表達式的類型是(各分支類型的)最近公共父類型或由編譯器推斷的最小上界(least upper bound)。如果某分支沒有值(如最后是 Unit),則表達式類型會相應地調整

val x = if (flag) 1 else 2        // Int
val y = if (flag) "ok" else null  // String?(可空)

典型用法與陷阱

  • 優先用 if 表達式代替臨時變量,代碼更簡潔、函數式風格更明顯。
  • 不要誤把 if 寫成布爾表達式賦值:在有分支返回布爾值與其它副作用混合時,容易讓類型變成 Boolean(見社區討論“guarding against unintentional return types”)。謹慎檢查每個分支返回的值類型。
  • if 支持嵌套與 block(塊)形式,塊內最后一行是該分支的結果(用于表達式場景)。

練習 1:使用 if/else 判斷奇偶數

目標: 編寫一個函數,它接受一個整數,然后返回一個字符串,告訴我們這個數是 “奇數” 還是 “偶數”。

要求:

  1. 創建一個名為 checkOddEven 的函數。
  2. 該函數接受一個 Int 類型的參數,名為 number
  3. 函數應返回一個 String 類型的結果。
  4. 使用 if/else 表達式來判斷 number 是否能被 2 整除。
  5. 如果能,則返回 “偶數”;如果不能,則返回 “奇數”。

參考代碼:

fun checkOddEven(number: Int): String {return if (number % 2 == 0) {"偶數"} else {"奇數"}
}fun main() {val num1 = 10val num2 = 7println("$num1${checkOddEven(num1)}") // 輸出: 10 是 偶數println("$num2${checkOddEven(num2)}") // 輸出: 7 是 奇數
}

筆記重點:

  • 在 Kotlin 中,if/else 是一個表達式 (expression),不是一個語句 (statement)。這意味著它可以有返回值。
  • 因此,我們可以直接使用 return if (...) 這樣的簡潔寫法。
  • 代碼塊 {} 中最后一行就是該塊的返回值。

when:強大且靈活的多分支工具

when 在 Kotlin 中是一個“一網打盡”的多用途分支表達式/語句:它既能完成傳統 switch 的工作,也能做更復雜的匹配(范圍、類型、任意條件),還可以作為表達式返回值。

基本語法(有 subject 與無 subject 兩種形式)

有 subject 的形式(最常見)

when (x) {0 -> print("x == 0")1, 2 -> print("x == 1 or x == 2")  // 多個值使用逗號分隔in 3..5 -> print("x ∈ [3,5]")else -> print("x is something else")
}

無 subject 的形式(相當于一連串 if/else if

when {x.isEmpty() -> println("empty")x.length > 5 -> println("long")else -> println("other")
}
  • when 分支可以使用逗號把多個匹配值合并到同一個分支。

when 作為表達式

when 可以返回值并直接賦給變量或返回:

val result = when (x) {1 -> "one"2 -> "two"else -> "many"
}

注意:當 when 被用作表達式時,編譯器要求覆蓋所有可能情況或提供 else(除非 when 是對 sealed class 的完全覆蓋情況)。

多種匹配條件支持(比 switch 更強)

每個 when 分支的條件可以是:

  • 常量(0, 'a', "s"
  • 多個常量(逗號分隔)
  • 區間或集合成員關系:in 1..10 / !in setOf(...)
  • 類型檢查:is String / !is Int(結合智能轉換 smart cast)
  • 任意表達式(在 無 subjectwhen 中尤其常見)
  • 函數調用的結果(在帶 subject 的 when(x) 中,分支條件會與 subject 的值做等值比較 —— 例如 parseInt(s) -> 表示“當 subject 等于 parseInt(s) 時”)。
when (val v: Any = getValue()) {is String -> println(v.length) // v 被智能轉換為 Stringis Int -> println(v + 1)      // v 是 Intelse -> println("unknown")
}

sealed classes 與可窮盡的 when

when 的 subject 類型是 sealed(或 sealed interface)的一個實例時,編譯器能在編譯期知道所有可能的子類型,從而檢查 when 是否窮盡覆蓋(exhaustive)。如果窮盡,則無需 else 分支;否則編譯器會要求 else。這使得 when 在實現狀態機或代數數據類型(ADT)匹配時非常強大。

sealed class Result {data class Success(val data: String): Result()object Failure: Result()
}fun handle(r: Result) = when (r) {is Result.Success -> println(r.data)Result.Failure -> println("failed")// 不需要 else(若覆蓋了所有子類)
}

6. 復雜分支與多語句塊

每個 when 的分支可以是單行表達式,也可以是一個塊({ ... }),塊的最后一行將作為該分支的返回值(當 when 作為表達式使用時)。這允許在分支中執行多步邏輯再返回最終值。(Kotlin)

val msg = when (cmd) {"ok" -> {log("ok received")"all good"}else -> "unknown"
}

練習 2:使用 when 表達式進行分數評級

目標: 編寫一個函數,根據輸入的分數(整數)給出對應的等級評價(字符串)。

要求:

  1. 創建一個名為 getGrade 的函數。
  2. 該函數接受一個 Int 類型的參數,名為 score
  3. 函數應返回一個 String 類型的結果。
  4. 使用 when 表達式實現以下評級邏輯:
    • score 為 100 時,返回 “滿分!”
    • score 在 90 到 99 之間時,返回 “優秀”
    • score 在 75 到 89 之間時,返回 “良好”
    • score 在 60 到 74 之間時,返回 “及格”
    • 否則,返回 “不及格”

參考代碼:

fun getGrade(score: Int): String {return when (score) {100 -> "滿分!"in 90..99 -> "優秀"in 75..89 -> "良好"in 60..74 -> "及格"else -> "不及格"}
}fun main() {println("95分評價: ${getGrade(95)}")   // 輸出: 95分評價: 優秀println("82分評價: ${getGrade(82)}")   // 輸出: 82分評價: 良好println("60分評價: ${getGrade(60)}")   // 輸出: 60分評價: 及格println("45分評價: ${getGrade(45)}")   // 輸出: 45分評價: 不及格println("100分評價: ${getGrade(100)}") // 輸出: 100分評價: 滿分!
}

筆記重點:

  • when 是 Kotlin 中用于替代傳統 switch 語句的更強大、更靈活的表達式。
  • 它可以匹配具體的值(如 100)。
  • 它可以用來檢查值是否在一個區間內(如 in 90..99)。
  • else 分支用于處理所有其他未匹配的情況,類似于 switch 中的 default
  • if 一樣,when 也是一個表達式,可以直接將其結果返回或賦值給變量。

Kotlin的循環語法

for 循環:更貼近 “foreach” 而非傳統的 C/Java 風格

  • Kotlin 沒有經典的三段式 for 遍歷語法,而是更傾向函數式、可迭代結構:

    for (item in collection) { ... }
    

    適用于數組、集合、字符串、范圍(只要實現了 Iterable

  • 常見用法:

    // Ranges
    for (i in 1..5) println(i)               // 1,2,3,4,5
    for (i in 5 downTo 1) println(i)         // 5,4,3,2,1
    for (i in 1..10 step 2) println(i)       // 1,3,5,7,9 :contentReference[oaicite:1]{index=1}// 數組、集合、字符串
    for (ch in "Kotlin") println(ch)
    for (elem in listOf(1,2,3)) println(elem) :contentReference[oaicite:2]{index=2}// 帶索引迭代
    for (i in arr.indices) println("index $i = ${arr[i]}")
    for ((i, v) in arr.withIndex()) println("$i -> $v") :contentReference[oaicite:3]{index=3}
    

    whiledo-while:標準條件循環

while

  • 初次檢查條件,若為 true 執行循環體。若初始條件為 false,則一次都不執行:

    while (condition) {// body
    }
    
    var i = 1
    while (i <= 5) {println(i)i++
    }
    

do-while

  • 循環體至少執行一次,之后再判斷條件決定是否繼續:

    do {// body
    } while (condition)
    

    常用場景:輸入驗證 / 重試邏輯等!


控制循環:breakcontinue

  • break:直接退出整個循環。
  • continue:跳過當前迭代,繼續下一次。
for (i in 1..10) {if (i == 5) break       // 遇到 5 時退出循環if (i % 2 == 0) continue // 偶數跳過println(i)
}

防止無限循環的技巧與注意

  • while (true) 可用于無限循環,通常配合 break 結束:

    while (true) {// ...if (someCondition) break
    }
    

    這種寫法雖常見,但要小心,確保終止條件有效

  • for 循環沒有原生的無限循環形式,這也是 Kotlin 設計上摒棄經典 C/Java 風格循環的體現

快速對照總結

場景推薦用法說明
遍歷集合、字符串、范圍等for (x in ...)簡潔、安全、函數式風格
條件循環while, do-while根據是否至少執行一次決定使用哪種
帶索引遍歷withIndex()indices獲取下標或值更方便
跳出/跳過循環break, continue靈活控制循環流程
避免無限循環小心 while(true) 使用必須確保有跳出條件

練習 3:使用 for 循環打印九九乘法表

目標: 在控制臺打印出一個經典、格式整齊的九九乘法表。

要求:

  1. 使用嵌套的 for 循環來完成。
  2. 外層循環控制乘法表的行(從 1 到 9)。
  3. 內層循環控制乘法表的列。關鍵點: 內層循環的次數應該依賴于外層循環當前的行數(例如,第 5 行只打印到 5 * 5)。
  4. 輸出格式應為 “{乘數1} * {乘數2} = {結果}”,并且為了美觀,每個算式之間用制表符 \t 分隔。
  5. 每打印完一行后,需要換行。

預期的輸出效果:

1 * 1 = 1   
2 * 1 = 2   2 * 2 = 4   
3 * 1 = 3   3 * 2 = 6   3 * 3 = 9   
4 * 1 = 4   4 * 2 = 8   4 * 3 = 12  4 * 4 = 16  
... (以此類推,直到第9行)
9 * 1 = 9   9 * 2 = 18  ...          9 * 9 = 81  

提示:

  • 你可以使用 1..9 來創建一個從 1 到 9 的整數區間 (range)。
  • print() 函數用于在同一行打印,而 println() 函數會在打印后換行。
fun printMultiplicationTable() {// 外層循環控制行,從1到9for (row in 1..9) {// 內層循環控制列,從1到當前行數for (col in 1..row) {// 打印乘法表達式,并用 \t 補齊,使其對齊print("$col * $row = ${col * row}\t")}// 每行結束后,換行println()}
}fun main() {printMultiplicationTable()
}

筆記重點:

  • for (variable in range) 是 Kotlin 中最常見的循環形式。
  • 1..9 創建了一個閉區間,包含 1 和 9。
  • 嵌套循環是處理二維結構(如表格、矩陣)的常用方法。
  • print()println() 的區別使用是格式化輸出的關鍵。

練習 4:使用 while 循環實現猜數字游戲

目標: 編寫一個簡單的猜數字游戲。程序會隨機生成一個 1 到 100 之間的整數,然后讓用戶反復猜測,直到猜對為止。

要求:

  1. 在程序開始時,生成一個 1 到 100 之間的隨機整數作為“謎底”。
  2. 使用 while 循環或 do-while 循環來不斷獲取用戶的輸入。
  3. 每次用戶輸入后,程序需要判斷:
    • 如果用戶猜的數字比謎底,則提示 “太大了,再猜!”。
    • 如果用戶猜的數字比謎底,則提示 “太小了,再猜!”。
    • 如果用戶猜對了,則提示 “恭喜你,猜對了!”,然后結束循環
  4. 記錄用戶總共猜了多少次,并在猜對后一并輸出。

提示:

  • 生成隨機數:可以使用 (1..100).random()
  • 讀取用戶輸入:可以使用 readln()readLine()。注意它返回的是 String?,你可能需要用 toIntOrNull() 轉換成整數并處理無效輸入。
fun guessTheNumber() {// 1. 生成1到100的隨機數作為謎底val secret = (1..100).random()var guessCount = 0var userGuess: Int? = nullprintln("我已經想好了一個 1 到 100 之間的數字,你來猜猜看!")// 2. 使用 while 循環,只要沒猜對就一直繼續while (userGuess != secret) {print("請輸入你猜的數字: ")// 讀取用戶輸入并轉換為整數userGuess = readln().toIntOrNull()// 增加猜測次數guessCount++// 檢查用戶輸入是否有效if (userGuess == null) {println("無效的輸入,請輸入一個數字!")continue // 跳過本次循環的剩余部分,直接開始下一次循環}// 3. 判斷大小并給出提示if (userGuess > secret) {println("太大了,再猜!")} else if (userGuess < secret) {println("太小了,再猜!")}}// 4. 猜對后,循環結束,打印祝賀信息println("恭喜你,猜對了!謎底就是 $secret。")println("你總共猜了 $guessCount 次。")
}fun main() {guessTheNumber()
}

筆記重點:

  • while (condition) 循環會在條件為 true 時持續執行。它適用于循環次數不確定的場景。
  • do-while 循環(未在此示例中使用)與 while 類似,但它保證循環體至少執行一次
  • 從控制臺讀取用戶輸入是與用戶交互的基礎。
  • toIntOrNull() 是一個安全的字符串轉整數方法,當轉換失敗時會返回 null,避免程序崩潰。
  • continue 關鍵字可以用來跳過當前循環的剩余代碼,直接進入下一次迭代。

Reference

  • Kotlin 官方 — Control flow(if / when 等)。(Kotlin)
  • Kotlin 官方 — Basic syntax(說明 if 為表達式示例)。(Kotlin)
  • Kotlin 官方 — Sealed classes(when 與 sealed 的 exhaustiveness)。(Kotlin)
  • Baeldung — Guide to when(講解 when 的常見變體與比較 switch)。(Baeldung on Kotlin)
  • GeeksforGeeks — Kotlin when expression 教程(多值、區間示例)。(GeeksforGeeks)
  • Kotlin 官方文檔,比如控制流章節解讀 whiledo-while(Kotlin),以及 for 循環和 ranges 介紹(programiz.com, Kotlin, GeeksforGeeks)。
  • 權威教程如 Baeldung、Programiz 的實戰示例(Baeldung on Kotlin, programiz.com)。
  • 社區討論強調設計理念與常見路徑(Kotlin Discussions, Reddit)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/95395.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/95395.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/95395.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

印度物聯網崛起:政策紅利下的千億藍海與本土化博弈

印度物聯網市場正處于快速發展階段,2025年市場規模預計達到200億美元,主要得益于政府"數字印度"計劃和智能城市項目的推動。蜂窩物聯網連接數在2024年同比增長34%,2025年Q1增速進一步提升至32%,其中智能電表部署和資產追蹤應用成為核心驅動力。然而,市場也面臨著…

html學習:

ok,今天準備學一下html&#xff0c;花費點時間整理一下&#xff1a; HTML標簽的語法格式 HTML 中的標簽就像關鍵字一樣&#xff0c;每個標簽都有自己的語義&#xff08;含義&#xff09;。 HTML 標簽的語法格式 屬性↓ <div class"begin">cyx</div>↑…

CRYPT32!PkiAsn1Decode函數分析的一個例子

第一部分&#xff1a; 0: kd> g Breakpoint 35 hit CRYPT32!PkiAsn1Decode: 001b:75c9af0c 55 push ebp 1: kd> kc# 00 CRYPT32!PkiAsn1Decode 01 CRYPT32!PkiAsn1DecodeAndAllocInfo 02 CRYPT32!PkiAsn1DecodeAndAllocInfoEx 03 CRYPT32!Asn1InfoDecode…

大模型蒸餾、大模型微調、RAG

前言&#xff1a; 有很多同學想學習大模型開發&#xff0c;又無從下手&#xff0c;網上一搜&#xff0c;鋪天蓋地的付費課程。又不想當韭菜&#xff0c;打破認知障礙&#xff0c;通過自學&#xff0c;改變自己&#xff0c;改變世界&#xff01; 一、大模型蒸餾、微調、RAG的適…

25高教社杯數模國賽【E題保姆級思路+問題分析】

注&#xff1a;本內容由”數模加油站“ 原創出品&#xff0c;雖無償分享&#xff0c;但創作不易。 歡迎參考teach&#xff0c;但請勿抄襲、盜賣或商用。 E 題 AI輔助智能體測 《國家學生體質健康標準》的頒布&#xff0c;有效地促進了大中小學生關注自身體質健康的發展&#xf…

基于單片機車內換氣溫度檢測空氣質量檢測系統Proteus仿真(含全部資料)

全套資料包含&#xff1a;Proteus仿真源文件keil C語言源程序AD原理圖流程圖元器件清單說明書等 資料下載&#xff1a; 通過網盤分享的文件&#xff1a;資料分享 鏈接: 百度網盤 請輸入提取碼 提取碼: tgnu 目錄 資料下載&#xff1a; Proteus仿真功能 項目文件資料&#…

MySQL子查詢的分類講解與實戰

精選專欄鏈接 &#x1f517; MySQL技術筆記專欄Redis技術筆記專欄大模型搭建專欄Python學習筆記專欄深度學習算法專欄 歡迎訂閱&#xff0c;點贊&#xff0b;關注&#xff0c;每日精進1%&#xff0c;與百萬開發者共攀技術珠峰 更多內容持續更新中&#xff01;希望能給大家帶來…

Leetcode 206. 反轉鏈表 迭代/遞歸

原題鏈接&#xff1a;Leetcode 206. 反轉鏈表 解法一&#xff1a;迭代 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* …

C++11新特性 | 歡迎來到現代C++的世界!

左值與右值 左值與右值的概念 可以被取地址的值為左值&#xff08;left value&#xff0c;簡稱lvalue&#xff09;&#xff0c;否則為右值&#xff08;right value&#xff0c;簡稱rvalue&#xff09;。 常見的左值、右值例子&#xff1a; // >>>>>>> 左值…

因為對象裝箱拆箱導致的空指針異常

今天業務突然提了個事件單&#xff0c;客戶添加承租人一直報錯&#xff0c;但是很奇怪&#xff0c;報錯信息是空的二話不說&#xff0c;先跟API組要了接口和參數&#xff0c;然后看日志然鵝&#xff0c;這個接口并沒有打印日志&#xff0c;只有一個e.printStackTrace()然后靜下…

Rust 在 Windows 環境下交叉編譯其他操作系統可執行文件的詳細指南

前言&#xff1a;為什么需要交叉編譯&#xff1f; 想象一下這樣的場景&#xff1a;你在 Windows 電腦上開發了一個 Rust 程序&#xff0c;希望它能在 Linux 服務器上運行&#xff0c;或者在朋友的 macOS 電腦上測試 —— 總不能為了編譯不同系統的版本&#xff0c;專門買一臺 …

Ubuntu系統配置鏡像源

要修改的文件 /etc/apt/sources.list操作步驟 1. 備份原文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak2. 編輯文件 sudo nano /etc/apt/sources.list3. 清空文件內容&#xff0c;填入以下內容 先獲取Ubuntu版本代號&#xff1a; lsb_release -cs然后根據版本填…

【Spring Cloud Alibaba】Sentinel(一)

【Spring Cloud Alibaba】Sentinel&#xff08;一&#xff09;1. 簡介2. 服務雪崩1. 簡介 Sentinel 是阿里巴巴開源的分布式系統的流量防護組件&#xff0c;主要用來做流量控制、熔斷降級、系統保護。它的定位類似于 Hystrix&#xff0c;但更側重在 流量治理 上。目前在微服務…

Delphi 5 操作Word表格選區問題解析

在 Delphi 5 中操作 Word 時&#xff0c;您遇到的 Selection.MoveDown 方法選中整行而不是僅移動一行的原因與 Word 的選擇機制和單元格內部結構有關。以下是詳細解釋和解決方案&#xff1a;問題分析單元格的選區范圍&#xff1a;當使用 .Cell(r, c).Select 選中單元格時&#…

小米fastboot不能被電腦識別但手機正常使用模式時能被電腦識別

小米手機USB連接電腦不識別解決方法 – MIUI歷史版本 小米手機USB連接電腦不識別解決方法 問題經驗 手機連接電腦通常會自動安裝驅動&#xff0c;如果驅動安裝失敗或是電腦不能識別手機設備&#xff0c;可嘗試下面方法。 1. 嘗試換根 USB 數據線&#xff0c;最好是手機原…

Git 版本管理工具基本操作匯總—命令總結

通常&#xff0c;很多朋友在使用 Git 的時候都會直接用 IDE 中集成的插件或者自帶的工具等來實現代碼的拉取、提交、合并以及其他操作&#xff0c;當然這肯定也是可以的&#xff0c;但是長期這樣子操作&#xff0c;我們就會忽略掉 Git 業務運行的底層邏輯。那么&#xff0c;我這…

自學嵌入式第三十三天:網絡編程-UDP

一、OSI模型(open system interconnect)開放系統互聯模型&#xff0c;分為7層應用層&#xff1a;為網絡用戶提供各種服務&#xff0c;例如電子郵件、文件傳輸等&#xff1b;表示層&#xff1a;為不同主機間的通信提供統一的數據表示形式。加密解密&#xff0c;壓縮&#xff1b;…

A*(Astar)算法詳解與應用

算法背景A*&#xff08;A-Star&#xff09;算法是一種在圖形平面上&#xff0c;有多個節點的路徑中&#xff0c;求出最低通過成本的算法。其歷史可以追溯到早期的圖搜索算法&#xff0c;如Dijkstra算法和貪心最佳優先搜索&#xff08;Greedy Best-First Search&#xff09;。是…

word刪除指定頁面

常規程序因為wps的 .docx 文件是基于段落和節的結構&#xff0c;而不是“物理頁”&#xff0c;所以無法直接按“第幾頁”刪除在普通程序里面無法讀取到他的頁碼&#xff0c;但是在宏編程里面他能讀取到頁碼&#xff0c;我們就根據宏編程來這樣刪除。程序會自動打開選擇要刪除的…