--- title: 'Kotlin 介紹 - 與 Java 基礎差異' disqus: kyleAlien --- Kotlin 介紹 - 與 Java 基礎差異 === ## Overview of Content 以下參考,第一行代碼 (第三版), Kotlin 進階實戰 如有引用參考本文章請詳註出處,感謝 :smile: :::success * 如果喜歡讀更好看一點的網頁版本,可以到我新做的網站 [**DevTech Ascendancy Hub**](https://devtechascendancy.com/) 本篇文章對應的是 [**Kotlin 與 Java 比較 | Kotlin 生態、入門 | Kotlin 特點、基礎**](https://devtechascendancy.com/kotlin-vs-java-ecosystem-intro-features-basics/) ::: [TOC] ## Kotlin 簡介 Kotlin 是由 [**JetBrains 公司**](https://www.jetbrains.com/zh-cn/company/) 開發與設計,2011 就已釋出第一個版本,並在 2012 年將其開源,2016 年 Kotlin 發布了正式 1.0 版,並在自家的 IDE 開發工具 `IntelliJIDEA` 加入該語言 **Kotlin 是基於 JVM 的語言**,所以它可以很好的跟 Java 相容,並且它不只可以開發 Android App 甚至可以開發後端服務、編譯成 JavaScript 程式 :::info * Kotlin 是 JetBrains 團隊開發出來的程式語言,其取名也源自於 **聖彼得堡附近的 [柯特林島](https://zh.m.wikipedia.org/zh-tw/%E7%A7%91%E7%89%B9%E6%9E%97%E5%B3%B6)** (俄羅斯附近) ::: ### Kotlin 特性 * Kotlin 語言有以下幾個高級語言特性 (收集了各個語言的專長 (`Python`, `Java`, `C#`, `JavaScript`, `Scala`, `Groovy`... 等等) 1. **函數(方法)**:高階函數 & Lambda 表達式 2. **防止 `NPE`**:空類型,`Elvis` 表達式,Scope Function 3. **Lazy loading**:懶加載,在需要時才創建資源,並且 Lazy loading **默認執行序(線程)安全** 4. **DSL 編程**:如同 Groovy 一樣的 DSL 編程 5. **Thread 管理**:以往在 Java Multi Thread 中我們常常會耗費 CPU 時間來做上下文切換,而 **在 Kotlin 中,有開發 `Coroutine` library 幫助我們做快速的上下文切換** :::success * 關於 Kotlin 更多 Coroutine 的使用請看 [**Coroutine - 協程**](https://hackmd.io/ggeGXU86T1uzhN8rVD8MHQ) ::: ### Kotlin & JVM 虛擬機 * 在 Android Java 有使用版權問題([**甲骨文、Google十年恩怨落幕!90億美元Java案大翻盤**](https://www.bnext.com.tw/article/62139/google-v-oracle-supreme-court-declares-fair?)),而 JVM 並沒有版權問題,這也就是為何 Kotlin 可以編譯出 Android 能夠接受的語言,其原因主要是因為 **JVM 透過翻譯字節碼(`Byte code`)來運行程式**,**而 Java、Kotlin 都是翻譯型語言,透過 JVM 翻譯過後都是相同的** > 這是基於平台開發語言抽象化的優點,讓語言本身面向的是 JVM 虛擬機,只要編譯出 JVM 可識別的 `Byte code` 就可以在不同平台上運行 :::info * **翻譯型 & 編譯型 ?** > **`編譯型`**:典型的編譯型語言像是 C、C++ 都屬於編譯型語言,**它會針對當前的 CPU 編譯成對應的二進制文件** > **`翻譯型`**:需要翻譯成第三方能夠看得懂的語言,再由第三方翻譯成二進制碼給 CPU 做程式運行,就像是 Java、Python 語言 兩者來說翻譯型語言的共通性較強,但相對的它的效率較低,它的特點剛好與編譯型語言相反 ::: 編譯概念圖如下 > ![](https://i.imgur.com/YqWImiz.png) ## Kotlin 發展 Kotlin 的發展以目前來看,是作為 **Java 的輔助、加強**(可從上面的輔助看出),不會完全的取代 Java ### Kotlin 生態圈 * Kotlin 目前已經是 Android App 開發的主流語言(官方推薦, [**Kotlin and Android**](https://developer.android.com/kotlin?hl=zh-tw)),除了一動端之外後端也可以很好的使用 Kotlin(後端開發常使用的 Spring 也推薦 Kotlin) * Kotlin 不只可以編譯成 Java 語言,也可以直接編譯成 `Binary code` & `Js code`,對於跨平台編譯也佔據一席之地([**kotlin multiplatform**](https://kotlinlang.org/docs/multiplatform.html)) * Kotlin 支援多平台 & 語言,其中包括 `JVM`, `Android`, `iOS`, `JavaScript`, `Linux`, `Windows`, `Mac` 甚至嵌入式 `STM32` :::success * JetBrains 提供多平台開發 `Kotlin Multiplatform Mobile` (KMM) ::: ## 與 Java 基礎差異 * 程式執行主要分為三種方式執行(以程式結構化的概念去思考,分為三點去討論!) 1. **順序語句** : 如同 Java 是由上往下單句執行 2. **條件語句** : 條件判斷 `if/else`,**Kotlin 沒有 `switch` 關鍵字,並使用了 `when` 取代** 3. **循環語句** : `for/while` 條件循環 ### Kotlin 變量宣告 * Java 中要定義一個遍量必須聲明變量的型態 (int a = 20),Kotlin 宣告時只允許在變量前聲明 **var**、**val** 兩個關鍵字,並且有自動推倒的特性 | kotlin 變量關鍵字 | 與 Java 比對 | 舉例 | | -------- | -------- | -------- | | var | 該變量可改變 | var A | | val | 如同**在變量前使用 final 描述**,說明該變量是不可改變的 | val B | * 先說明幾個特性 ^1.^ **Kotlin 結語不需使用 `;` 分號**、^2.^ Kotlni 類型可以**自動推倒** (也可以自行設定) ```kotlin= // 包名不建議大寫開頭 package class_1 /** * 變數 & 型態 * 變數皆使用 var、val 定義 * var : 可變參數 * val : 不可變參數,其功能是為了解決 Java 中 final 不常被使用的問題 */ fun main() { println("Hello Kotlin!") // 結束不須分號 var a = 10 a = 15 // a = "Boy"; Err: var 推導後類型不可變 println("a = $a"); val b = 20 // b = 25 Err: val 描述後不可再賦值, Val cannot be reassigned println("b = $b"); var c : Int = 30 // ':' 類型指定 c = 33 println("c = $c"); var d : Short = 1 // Kotlin 完全秉棄了 Java 的基礎類型,"全部皆為對象",基礎數據類型全部大寫 d = 11 println("d = $d"); } ``` :::warning * 關鍵字、自動推倒,要注意幾點: 1. **`var` 類型推導完成後,不可再賦予其他類型** 2. `val` 必須賦予值,並且不能再對其變量進行更改,否則編譯器會提是 `Val cannot be reassigned` 錯誤 3. 自動推導並非每次都有用,若是我們對一個變量延遲賦值,Kotlin 就無法自動推倒其類型,這時可以使用 `:` 指定 ```kotlin= // lateinit 延遲初始化,就必須指定參數類型 lateinit var name: String ``` 4. **Kotlin 內所的事物皆為對象**,也就是 **沒有基礎數據類型** (其實也就是將 Java 每一個數據類型開頭改為大寫) | Java 基礎數據類型 | Kotlin 對象數據類型 | | -------- | -------- | | boolean | Boolean | | char | Char | | byte | Boolean | | short | Short | | int | Int | | long | Long | | float | Float | | double | Double | ::: **--實作結果--** > ![](https://i.imgur.com/g0b39EU.png) :::success * **為何設計 `val` 關鍵字** **`val` 的設計是為了解決 ++Java 中 final 描述詞沒有被正當使用的情況++**;一般來說 **類、變量若是沒有被使用應該都宣告為 final,以免被誤用**,這是一個好習慣 ::: ### if / else & when 判斷 * 以下會先說 if 與 Java 不同的使用地方,其最大的不同在於 **Kotlin 的 if 可以直接返回數值,並且不需要 return 關鍵字** * **when 作為取代 switch 的關鍵字**,並且 Kotlin 對其功能進行了拓展,可以搭配 `is` 使用在類的判斷相當於 java instanceof (取代 case,並 **省略了 break 關鍵字**),並且最後使用 else (取代 default) 1. **`if/else` 判斷** ```kotlin= // Kotlin's if 可使用如同 Java's if fun useIf(n1: Int, n2: Int) : String { var result = "" if (n1 > n2) { result = "$n1 is Bigger" } else { result = "$n2 is Bigger" } return result } // Kotlin's if 可以有返回值!! // 該返回值在代碼中的最後一行 (不須 return fun useIfDiff(n1: Int, n2: Int) : String { return if (n1 > n2) { "$n1 is Bigger" } else { return "$n2 is Bigger" // return 可有可無 } } fun useIfSimple(n1: Int, n2: Int) = if (n1 > n2) { "$n1 is Bigger" } else { "$n2 is Bigger" // return 不可以用在 = 符號 } ``` 2. **`when` 代替 `switch`** when 語句如同 if 是可以有返回值 > ![](https://i.imgur.com/m4JvKZc.png) ```kotlin= fun useWhenSimple(id: Int) = when(id) { 1 -> "A" 2 -> { // 超過一行時使用大括號 "B" } 3 -> "C" else -> "Non" // like default } // when 可以配合 is 一起使用,相當於 Java 的 instanceof fun useIs(id: Number) : Unit = when(id) { is Int -> println("Params is Int") is Double -> println("Params is Double") is Float -> println("Params is Float") else -> println("Cannot decide Type") } // 若要直接使用參數判斷,when 就不需要括弧,並且可以 對關鍵字進行操作 fun useWhenWithParams(id: Number) = when { id is Byte -> println("Params is Int") id == 11 -> println("Params is 11") id == 11.1 -> println("Params is 11.1") id.toFloat() == 1.0f -> { println("Params is 1.0f") } else -> println("Cannot decide Type") } ``` :::warning * `==` 符號在 Java 中是用來判斷兩個內存地址是否相同,而 Kotlin `==` 符號則是判斷對象、字串是否相同,相當於 equals 的方法 | 功能 | Java 關鍵字 | Kotlin 關鍵字 | | -------- | -------- | -------- | | 對象是否相等 (內容) | `equals` | `==` | | 內存(記憶體)地址是否相等 | `==` | `===` | ```kotlin= package class_1 fun main() { val a : String = "Hello" val b : String = String(StringBuffer("Hello")) println("a.equals(b): ${a.equals(b)}") println("a == b: ${a == b}") println("a === b: ${a === b}") } ``` > ![](https://i.imgur.com/GTSfwao.png) ::: 3. 測試順序語句、條件語句、循環語句 ```kotlin= package class_1 /** * 程式的運營主要有三種型語句 * 1. 順序語句 (執行程式的順序 * 2. 條件語句 (if/else、when * 3. 循環語句 (for、while */ fun main() { var r = useIf(11, 2) println("Answer: $r") r = useIfDiff(11, 22) println("Answer: $r") r = useIfSimple(33, 22) println("Answer: $r") // -------------------------------------------- r = useWhenSimple(3) println("When(id): $r") useIs(12.3f) useWhenWithParams(11) useWhenWithParams(1.0) } ``` > ![](https://i.imgur.com/5GI9Dag.png) ### 循環 & 區間 - 語法糖 * Kotlin 語言的特色之一,就是它有提供一系列優秀的「語法糖」,可以 **有利於開發速度、可讀性**!以下是 Kotlin 常用的 循環 & 區間 的關鍵字 | 關鍵字(符號) | 功能 | | -------- | -------- | | until | 同樣是個區間,但是不包含最後一個元素 (左閉右開) | | in | 判斷是否符合在區間內,會配合著 `..` 一起使用 (類似 Python) | | `..` | 區間,**包含最後一個數字** (`until` 則不包含) | | step | 前進的數量 | | downTo | 前面都是升序,`downTo` 則是降序讀取 | ```kotlin= /** * 循環: Kotlin 也提供 for & while * while 與 Java、C、C++ 相同 * for-i 轉為 foreach,並大幅增強改變為 for-in * * 區間: 使用關鍵字 `..` 可以表示數值的區間 (小到大) * 用數學的表達方式就是 [0, 10] */ fun main() { println("3 in 0..10: ${3 in 0..10}") // 以下如同 [0, 2, 4, 6, 8. 10] println("3 in 0..10 step 2: ${3 in 0..10 step 2}") // false // 以下如同 [0, 3, 6, 9] println("3 in 0..10 step 3: ${3 in 0..10 step 3}") // true // 以下如同 [10, 7, 4, 1] println("4 in 10 downTo 0 step 3: ${4 in 10 downTo 0 step 3}") // true useForIn() useForInStep() useForInUntil() useForInDownTo() } fun useForIn() { for (i in 0 .. 5) { println("$i") } } fun useForInStep() { for (i in 0 .. 5 step 2) { // 一次前進 2 println("Step: $i") } } // 達成左閉右開 fun useForInUntil() { for (i in 0 until 5) { // 當然可以與 step 結合 (0 ~ 4) println("until: $i") } } // 區間 `..` & Until 都是 "升序",downTo 則是降序 fun useForInDownTo() { for (i in 5 downTo 0 step 2) { // 區間 [10,0],並配合 step 使用 println("downTo: $i") } } ``` > ![](https://i.imgur.com/s2IV3Db.png) :::info * 指定次數的 For 迴圈會使用 `in` + `until` ```kotlin= fun forControl(times : Int = 10) { for (i in 0 until times) { // TODO: } } ``` ::: ### tag 標籤 - @ * 上面的循環語句可以配合標籤一起使用;一般來說跳出迴圈必須使用 `break`,在 Kotlin 中也可以使用「**標籤**」來代替;**標籤的功能就像是 C/C++ 的 `goto` 一般**,可以直接轉會到那一行 > 標籤格式: `<標籤名稱>@` ```java= package class_1 fun main() { customFor() println() kotlinTag() } // 傳統 for 用法 fun customFor() { for(i in 0..5) { println("customFor i: $i") for (j in 0..5) { if (i == 2) { println("Till 2 use break") break } } if(i == 4) break } } /** * 使用標籤達到相同的效果 */ fun kotlinTag() { // 標籤 Hi@ for(i in 0..5) { println("kotlinTag i: $i") Tag@for (j in 0..5) { if (i == 2) { println("Till 2 use Break & Tag") break@Tag // 跳出 tag 標籤 } } if(i == 4) break@Hi } } ``` **--實作結果--** > ![](https://i.imgur.com/ZvKAjEy.png) :::info * **Class 類就自帶標籤,++標籤與類同名++**,範例如下 ```java= class PC { var CPU = "Intel-core-i5"; var ram = 16; fun info2() { // 返回 this@PC,也就是 PC 類 println("Cpu: ${this@PC.CPU}, ram: ${this@PC.CPU}") } } ``` ::: ## 更多的 Kotlin 語言相關文章 在這裡,我們提供了一系列豐富且深入的 Kotlin 語言相關文章,涵蓋了從基礎到進階的各個方面。讓我們一起來探索這些精彩內容! ### Kotlin 語言基礎 * **Kotlin 語言基礎**:想要建立堅實的 Kotlin 基礎?以下這些文章將帶你深入探索 Kotlin 的關鍵基礎和概念,幫你打造更堅固的 Kotlin 語言基礎 :::info * [**Kotlin 函數、類、屬性 | DataClass、Sealed、Object 關鍵字 | Enum、Companion、NPE**](https://devtechascendancy.com/kotlin-functions_oop_dataclass_sealed_object/) * [**深入探究 Kotlin 與 Java 泛型:擦除、取得泛型類型、型變、投影 | 協變、逆變**](https://devtechascendancy.com/explore-kotlin-java-generics_type_erasure/) * [**深入 Kotlin 函數特性:Inline、擴展、標準函數全解析 | 提升程式碼效能與可讀性**](https://devtechascendancy.com/kotlin_inline_extensions_standards-func/) * [**Kotlin DSL、操作符、中綴表達式 Infix | DSL 詳解 | DSL 設計與應用**](https://devtechascendancy.com/kotlin-dsl-operators-infix-explained/) ::: ### Kotlin 特性、特點 * **Kotlin 特性、特點**:探索 Kotlin 的獨特特性和功能,加深對 Kotlin 語言的理解,並增強對於語言特性的應用 :::warning * [**Kotlin 代理與懶加載機制:使用、lazy 深度解析**](https://devtechascendancy.com/kotlin-delegate_java-proxy_lateinit_lazy/) * [**Kotlin Lambda 編程 & Bytecode | Array & Collections 集合 | 集合函數式 API**](https://devtechascendancy.com/kotlin-lambda-bytecode-array-collections-functional/) * [**深入理解 Kotlin:智能推斷與 Contact 規則**](https://devtechascendancy.com/kotlin-smart-inference-contract-rules-guide/) ::: ### Kotlin 進階:協程、響應式、異步 * **Kotlin 進階:協程、響應式、異步**:若想深入學習 Kotlin 的進階主題,包括協程應用、Channel 使用、以及 Flow 的探索,請查看以下文章 :::danger * [**應用 Kotlin 協程:對比 Thread、創建協程、任務掛起 | Dispatcher、CoroutineContext、CoroutineScope**](https://devtechascendancy.com/applied-kotlin-coroutines-in-depth-guide/) * [**Kotlin Channel 使用介紹 | Select、Actor | 生產者消費者**](https://devtechascendancy.com/kotlin-channel_select_actor_cs/) * [**探索 Kotlin Flow:基本使用、RxJava 對比、背壓機制 | Flow 細節**](https://devtechascendancy.com/kotlin-flow-usage_compare-rx_backpressure/) ::: ## Appendix & FAQ :::info ::: ###### tags: `Kotlin`