【Kotlin回顧】2.基礎語法

語言: CN / TW / HK

theme: cyanosis


開啟掘金成長之旅!這是我參與「掘金日新計劃 · 12 月更文挑戰」的第2天,點選檢視活動詳情

1.變數

/* 關鍵字 變數型別 ↓ ↓ */ var price: Int = 100; /* ↑ ↑ 變數名 變數值 */

變數的關鍵字有valvar,前者是不可變變數相當於Java中的final變數,後者是可變變數對應Java的普通變數,大多數情況下應該儘可能的使用val,這樣就遵守了Kotlin的【不可變特性】

在Kotlin中【;】可以不用寫,同時Kotlin還支援【型別推導】例如

``` val num = 1

val str = "Hello World"

val isAudlt = false ```

上面的程式碼在後面並沒有宣告變數型別,這就是因為Kotlin的【型別推導】

2.基礎型別

在Kotlin中一切都是物件,在Java中有原始型別(int)和包裝型別(Integer),其中原始型別不是物件,只有包裝型別才是,而在Kotlin中就規避了這個問題,型別是完全的面向物件的,它的型別如下表所示

| Type | Bit width | 備註 | | ------- | --------- | ------------------- | | Double | 64 | Kotlin沒有double | | Float | 32 | Kotlin沒有float | | Long | 64 | Kotlin沒有long | | Int | 32 | Kotlin沒有int/Integer | | Short | 16 | Kotlin沒有short | | Char | 16 | Kotlin沒有char | | Byte | 8 | Kotlin沒有byte | | Boolean | 8 | Kotlin沒有boolean |

Kotlin這麼做的好處是可以從下面這段程式碼得知

val i:Double = 1.toDouble()

可以直接進行型別轉換,在Java中因為原始型別不是一個物件因此無法實現這樣便捷的操作

  • 空安全

Kotlin中既然一切都為物件那麼就可以定義空的變量了,在Java中可以直接在變數後賦值【null】即可定義空變數,但是在Kotlin中不可以這麼做,Kotlin中想定義一個空變數需要用如下方法:

``` val x : String = "" //不可為空的變數

val y : String? = null //可以為空的變數 ```

同時還需要注意的是不能把y的值賦給x,因為x是不可為空的

  • 數字型別

Kotlin中的數字型別與Java中的數字型別一致

val int = 1 //整數預設會被推導為“Int”型別; val long = 1234567L //Long型別,我們則需要使用“L”字尾; val double = 13.14 //小數預設會被推導為“Double”,我們不需要使用“D”字尾; val float = 13.14F //Float型別,我們需要使用“F”字尾; val hexadecimal = 0xAF //使用“0x”,來代表十六進位制字面量; val binary = 0b01010101 //使用“0b”,來代表二進位制字面量。

但是,對於數字型別的轉換,Kotlin 與 Java 的轉換行為是不一樣的。Java 可以隱式轉換數字型別,而 Kotlin 更推崇顯式轉換。 在Kotlin中數字型別的轉換如下所示:

val i : Int = 0 val j : Long = i.toLong()

類似的函式還有 toByte()、toShort()、toInt()、toLong()、toFloat()、toDouble()、toChar() 等等

  • 布林型別

布林型別與Java是一樣的,只有true和false兩個值,定義如下:

val x = false val y = true

  • 字元:Char

字元的定義跟Java類似只能代表單個字元,都是用【' '】定義的

val x = 'A'

  • 字串:String

Kotlin的字串定義用【" "】和【""" """】 ,前者就是普通的字串定義,後者是在定義時是什麼樣打印出的日誌就是什麼樣

``` val x = "Hello Kotlin” //輸出日誌:Hello Kotlin

val y = """ Hello World 今天是2022年 """ //輸出日誌: //Hello World //今天是2022年
```

  • 陣列

在Kotlin中陣列的定義使用arrayOf(),在括號中可以新增陣列的元素,同時因為Kotlin具有型別推導的特性,因此定義陣列的時候是不需要新增陣列型別的,程式碼如下:

val arrayInt = arrayOf(1, 2, 3) val arrayString = arrayOf("apple", "pear")

在Java中我們常常需要運算元組,例如獲取陣列的長度需要length()方法,取出陣列的元素需要arrayInt[index]跟集合是不一樣的,但是在Kotlin中運算元組和操作集合的方法基本是一樣的:

val size = arrayInt.size //獲取陣列長度 val item = arrayInt[0] //獲取arrayInt的第【0】個元素

以上就是Kotlin的基礎型別的內容,這裡還要提一個Kotlin的特性——字串拼接 ,程式碼如下:

``` val a = "Hello" println("$a Kotlin") //輸出日誌:Hello Kotlin

val arrayString = arrayOf("apple", "pear") println("arrayString陣列的第【0】個元素的值是:${arrayString[0]}") //輸出日誌:arrayString陣列的第【0】個元素的值是:apple ```

可以看到這個比Java真的是方便不少,具體用法就是如果只是單純的拼接只需要加上【$】後面再跟上變數名或者字串即可,如果需要從某個陣列或者集合或者物件中取值就需要在加上【$】後再加上【{}】,在花括號中寫入取值程式碼即可。

3.函式

  • 函式宣告

Kotlin宣告一個函式的程式碼如下:

/* 關鍵字 函式名 引數型別 返回值型別 ↓ ↓ ↓ ↓ */ fun helloFunction(name: String): String { return "Hello $name !" }/* ↑ 花括號內為:函式體 */

    • 使用了 fun 關鍵字來定義函式;
    • 函式名稱,使用的是駝峰命名法(特殊函式除外);
    • 函式引數,是以 (name: String) 這樣的形式傳遞的,這代表了引數型別為 String 型別;
    • 返回值型別,緊跟在引數的後面;
    • 最後是花括號內的函式體,它代表了整個函式的邏輯。

上面的程式碼中函式體只有一行程式碼因此可以這麼寫

fun helloFunction(name: String): String = "Hello $name !"

這樣就省去了return和花括號,同時因為Kotlin具有型別推導的特性還可進一步優化程式碼:

fun helloFunction(name: String) = "Hello $name !"

這種方式的寫法被稱單一表達式函式

  • 函式呼叫

函式呼叫的呼叫跟Java類似,也是helloFunction("Kotlin")的方法,但是如果存在多個引數的情況下就會出現如下情況

``` fun createStudent( name: String, age: Int, gradle: String, teacher: String, subjects: String, score: Int, ranking: Int ) { //.. }

createStudent("張三", 12, "六年級", "李四", "數學", 100, 1) ```

呼叫傳參的時候不知道引數具體代表的是哪個欄位,這個在新版的IDE上會有提示,但是該記錄咱還是要記錄一下的

kotlin的特性其實可以這麼寫:

fun main() { createStudent( name = "張三", age = 12, gradle = "六年級", teacher = "李四", subjects = "數學", score = 100, ranking = 1 ) }

Kotlin的函式呼叫還有一個特性就是預設引數,程式碼如下

``` fun createStudent( name: String, age: Int, gradle: String = "六年級", teacher: String = "李四", subjects: String = "數學", score: Int, ranking: Int ) { //.. }

fun main() { createStudent( name = "張三", age = 12, score = 100, ranking = 1 ) } ```

在函式中定義的引數有了預設值那麼我們在呼叫這個函式時就可以不傳。

4.流程控制

Kotlin當中的流程控制主要有ifwhenwhile和for

  • if

在Java中使用if一般都這麼寫

``` val i = 1 if (i > 0) { print("Big") } else { print("Small") }

輸出結果: Big ```

在Kotlin中也可以這麼寫(這是一句廢話),但是它可以作為表示式來使用時就可以這麼寫,輸出結果是一致的

val i = 1 val message = if (i > 0) "Big" else "Small"

另外,Kotlin中有【可空型別】和【不可空型別】,一般情況下我們都會遇到可空的變數,這就需要判斷是否為空,那麼我們就可以這麼寫

``` fun getLength(text: String?): Int { return if (text != null) text.length else 0 }

//優化後 fun getLength(text: String?): Int { return text?.length ?: 0 } ```

這種簡化的寫法叫做 Elvis 表示式。

  • when

通常情況下當if/else大於兩個分支的時候就要用到when了,它與switch case的用法類似,但是它更好用因為when還可以作為表示式使用給變數賦值

``` val i: Int = 1

when(i) { 1 -> print("男") 2 -> print("女") else -> print("未知") }

//輸出結果:男

val i: Int = 1

val i = 1 val gender = when (i) { 1 -> "男" 2 -> "女" else -> "未知" } print(gender)

//輸出結果:男 ```

switch case的區別是when的結尾必須要有else否則就會報錯。

  • 迴圈迭代:while

Kotlin的while的用法與Java類似沒什麼太大區別

``` var i = 0 while (i <= 2) { println(i) i++ }

var j = 0 do { println(j) j++ } while (j <= 2)

輸出結果: 0 1 2 0 1 2 ```

  • 迭代迴圈: for

for迴圈就跟Java有很大的區別了

首先我們先遍歷一個數組

``` val arrayInt = (1, 2, 3) for(i in arratInt){ println(i) }

//依次輸出:1、2、3 ```

遍歷一個區間

``` val oneTwoThree = 1..3 //代表[1, 3]

for(i in oneTwoThree){ println(i) } //依次輸出:1、2、3 ```

逆序迭代一個區間

``` for (i in 6 downTo 0 step 2) { println(i) }

輸出結果: 6 4 2 0 ```

上面這行程式碼的意思是逆序從6到0每隔兩個數迭代

這裡要注意的是逆序不能用區間【6..0】來定義,這樣是不被Kotlin允許的。

5.思考題

雖然 Kotlin 在語法層面摒棄了“原始型別”,但有時候為了效能考慮,我們確實需要用“原始型別”。這時候我們應該怎麼辦?

  • 如果這個變數在定義的時候存在可能為空的情況就會被編譯成Java的包裝型別,如果這個變數不可能為空那它被編譯後就是Java的原始型別。