Overview of Content
這篇文章旨在為那些已經熟悉 Java 語言的讀者提供對 Kotlin 的了解。
我們將探討 Kotlin 的基本特性、與 JVM 虛擬機的關聯,以及它在軟體開發領域中的發展趨勢。
文章首先介紹Kotlin的基礎知識,包括變量宣告、判斷語句如if/else和when的使用,以及循環和區間的語法糖。接著,我們深入探討 Kotlin 與 Java 之間的基本差異,使讀者能夠更容易地轉換在 Java 中的知識和技能到 Kotlin 上。
此外,我們將簡要介紹Kotlin在多平台生態圈中的角色,以及如何在項目中有效地使用 tag 標籤。透過本文,讀者將能夠建立起對Kotlin語言的基礎理解,並掌握在實際項目中應用這一現代語言的能力。
如有引用參考本文章請詳註出處,感謝 😀
Kotlin 語言簡介
Kotlin 是由 JetBrains 公司 開發與設計,2011 就已釋出第一個版本,並在 2012 年將其開源,2016 年 Kotlin 發布了正式 1.0 版,並在自家的 IDE 開發工具 IntelliJIDEA
加入該語言
Kotlin 是基於 JVM 的語言,所以它可以很好的跟 Java 相容,並且它不只可以開發 Android App 甚至可以開發後端服務、編譯成 JavaScript 程式
● Kotlin 是 JetBrains 團隊開發出來的程式語言,其取名也源自於 聖彼得堡附近的 柯特林島 (俄羅斯附近)
Kotlin 特性
● Kotlin 語言有以下幾個高級語言特性 (收集了各個語言的專長 (Python
, Java
, C#
, JavaScript
, Scala
, Groovy
... 等等)
A. 函數(方法):高階函數 & Lambda 表達式
B. 防止 NPE
:空類型,Elvis
表達式,Scope Function
C. Lazy loading:懶加載,在需要時才創建資源,並且 Lazy loading 默認執行序(線程)安全
D. DSL 編程:如同 Groovy 一樣的 DSL 編程
E. Thread 管理:以往在 Java Multi Thread 中我們常常會耗費 CPU 時間來做上下文切換,而 在 Kotlin 中,有開發 Coroutine
library 幫助我們做快速的上下文切換
● 關於 Kotlin 更多 Coroutine 的使用請看 Coroutine - 協程
Kotlin & JVM 虛擬機
● 在 Android Java 有使用版權問題(甲骨文、Google十年恩怨落幕!90億美元Java案大翻盤),而 JVM 並沒有版權問題,這也就是為何 Kotlin 可以編譯出 Android 能夠接受的語言,其原因主要是因為 JVM 透過翻譯字節碼(Byte code
)來運行程式,而 Java、Kotlin 都是翻譯型語言,透過 JVM 翻譯過後都是相同的
這是基於平台開發語言抽象化的優點,讓語言本身面向的是 JVM 虛擬機,只要編譯出 JVM 可識別的
Byte code
就可以在不同平台上運行
● 翻譯型 & 編譯型 ?
編譯型
:典型的編譯型語言像是 C、C 都屬於編譯型語言,它會針對當前的 CPU 編譯成對應的二進制文件
翻譯型
:需要翻譯成第三方能夠看得懂的語言,再由第三方翻譯成二進制碼給 CPU 做程式運行,就像是 Java、Python 語言兩者來說翻譯型語言的共通性較強,但相對的它的效率較低,它的特點剛好與編譯型語言相反
編譯概念圖如下
Kotlin 發展
Kotlin 的發展以目前來看,是作為 Java 的輔助、加強(可從上面的輔助看出),不會完全的取代 Java
Kotlin 生態圈:多平台
● Kotlin 目前已經是 Android App 開發的主流語言(官方推薦, Kotlin and Android),除了一動端之外後端也可以很好的使用 Kotlin(後端開發常使用的 Spring 也推薦 Kotlin)
● Kotlin 不只可以編譯成 Java 語言,也可以直接編譯成 Binary code
& Js code
,對於跨平台編譯也佔據一席之地(kotlin multiplatform)
● Kotlin 支援多平台 & 語言,其中包括 JVM
, Android
, iOS
, JavaScript
, Linux
, Windows
, Mac
甚至嵌入式 STM32
● JetBrains 提供多平台開發
Kotlin Multiplatform Mobile
(KMM)
Kotlin 與 Java 基礎差異
● 程式執行主要分為三種方式執行(以程式結構化的概念去思考,分為三點去討論!)
A. 順序語句 : 如同 Java 是由上往下單句執行
B. 條件語句 : 條件判斷 if/else
,Kotlin 沒有 switch
關鍵字,並使用了 when
取代
C. 循環語句 : for/while
條件循環
Kotlin 變量宣告
● Java 中要定義一個遍量必須聲明變量的型態 (int a = 20),Kotlin 宣告時只允許在變量前聲明 var、val 兩個關鍵字,並且有自動推倒的特性
kotlin 變量關鍵字 | 與 Java 比對 | 舉例 |
---|---|---|
var | 該變量可改變 | var A |
val | 如同在變量前使用 final 描述,說明該變量是不可改變的 | val B |
● 先說明幾個特性 1. Kotlin 結語不需使用 ;
分號、2. Kotlni 類型可以自動推倒 (也可以自行設定)
// 包名不建議大寫開頭
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");
}
● 關鍵字、自動推倒,要注意幾點:
A.
var
類型推導完成後,不可再賦予其他類型B.
val
必須賦予值,並且不能再對其變量進行更改,否則編譯器會提是Val cannot be reassigned
錯誤C. 自動推導並非每次都有用,若是我們對一個變量延遲賦值,Kotlin 就無法自動推倒其類型,這時可以使用
:
指定// lateinit 延遲初始化,就必須指定參數類型 lateinit var name: String
D. Kotlin 內所的事物皆為對象,也就是 沒有基礎數據類型 (其實也就是將 Java 每一個數據類型開頭改為大寫)
Java 基礎數據類型 Kotlin 對象數據類型 boolean Boolean char Char byte Boolean short Short int Int long Long float Float double Double
--實作結果--
● 為何設計
val
關鍵字
val
的設計是為了解決 Java 中 final 描述詞沒有被正當使用的情況;一般來說 類、變量若是沒有被使用應該都宣告為 final,以免被誤用,這是一個好習慣
Kotlin 判斷語句 if/else & when
● 以下會先說 if 與 Java 不同的使用地方,其最大的不同在於 Kotlin 的 if 可以直接返回數值,並且不需要 return 關鍵字
● when 作為取代 switch 的關鍵字,並且 Kotlin 對其功能進行了拓展,可以搭配 is
使用在類的判斷相當於 java instanceof (取代 case,並 省略了 break 關鍵字),並且最後使用 else (取代 default)
A. if/else
判斷
// 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 不可以用在 = 符號
}
B. when
代替 switch
when 語句如同 if 是可以有返回值
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")
}
●
符號在 Java 中是用來判斷兩個內存地址是否相同,而 Kotlin
符號則是判斷對象、字串是否相同,相當於 equals 的方法
功能 Java 關鍵字 Kotlin 關鍵字 對象是否相等 (內容) equals
==
內存(記憶體)地址是否相等 ==
===
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}") }
C. 測試順序語句、條件語句、循環語句
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)
}
循環 & 區間 - 語法糖
● Kotlin 語言的特色之一,就是它有提供一系列優秀的「語法糖」,可以 有利於開發速度、可讀性!以下是 Kotlin 常用的 循環 & 區間 的關鍵字
關鍵字(符號) | 功能 |
---|---|
until | 同樣是個區間,但是不包含最後一個元素 (左閉右開) |
in | 判斷是否符合在區間內,會配合著 .. 一起使用 (類似 Python) |
.. | 區間,包含最後一個數字 (until 則不包含) |
step | 前進的數量 |
downTo | 前面都是升序,downTo 則是降序讀取 |
/**
* 循環: 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")
}
}
● 指定次數的 For 迴圈會使用
in
+until
fun forControl(times : Int = 10) { for (i in 0 until times) { // TODO: } }
tag 標籤 - @
● 上面的循環語句可以配合標籤一起使用;一般來說跳出迴圈必須使用 break
,在 Kotlin 中也可以使用「標籤」來代替;標籤的功能就像是 C/C 的 goto
一般,可以直接轉會到那一行
標籤格式:
<標籤名稱>@
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
}
}
--實作結果--
● Class 類就自帶標籤,標籤與類同名,範例如下
class PC { var CPU = "Intel-core-i5"; var ram = 16; fun info2() { // 返回 this@PC,也就是 PC 類 println("Cpu: ${this@PC.CPU}, ram: ${this@PC.CPU}") } }