Kotlin 基礎(一)

1. 標識符

特定標識符field和it。在Kotlin語言中有兩個由編譯器定義的特定標識符,它們只能在特定場景中使用有特定的作用,而在其他的場景中可以做標識符使用。

提示:field標識符用於屬性訪問器中,訪問屬性支持字段;it標識符用於Lambda表達式中,在省略參數列表時作爲隱式參數,即不需要聲明就可以使用的參數。

    // 創建一個字符串數組
    var arrays = arrayListOf("A", "B", "C")
    // 遍歷
    arrays.forEach { println(it) }

2. 關鍵字

Kotlin語言中有70多個關鍵字,全部是小寫英文字母,以及!和?等字符構成。分爲3個大類:

硬關鍵字(Hard Keywords),硬關鍵字任何情況下都不能作爲標識符,具體包括如下關鍵字。

as、as?、break、class、continue、do、else、false、for、fun、if、in、!in、interface、is、!is、null、object、package、      return、super、this、throw、true、try、typealias、val、var、when和while。

軟關鍵字(Soft Keywords),是在它適用場景中不能作爲標識符,而其他場景中可以作爲標識符,具體包括如下關鍵字。

by、catch、constructor、delegate、dynamic、field、file、finally、get、import、init、param、property、receiver、set、
setparam和where。

修飾符關鍵字(Modifier Keywords),修飾符關鍵字是一種特殊的軟關鍵字,它們用來修飾函數、類、接口、參數和屬性等內容,在此場景中不能作爲標識符。而其他場景中可以作爲標識符,具體包括如下關鍵字。

abstract、annotation、companion、const、crossinline、data、enum、external、final、infix、inner、internal、lateinit、
noinline、open、operator、out、override、private、protected、public、reified、sealed、suspend、tailrec和vararg。

3. 變量和常量

1. 變量

 在Kotlin中聲明變量,就是在標識符的前面加上關鍵字var。

var str = "kotlin"
var i = 0
var price: Float = 10.08f

2. 常量和只讀變量

常量和只讀變量一旦初始化後就不能再被修改。在Kotlin聲明常量是在標識符的前面加上val或const val關鍵字.

它們的區別如下。

val聲明的是運行期常量,常量是在運行時初始化的

const val聲明的是編譯期常量,常量是在編譯時初始化,只能用於頂層常量聲明或聲明對象中的常量聲明,而且只能是String      或基本數據類型(整數、浮點等)。

提示: 編譯期常量(const val)相當於Java中public final static所修飾的常量。而運行期常量(val)相當於Java中final所修飾的    常量。

const val str = "compile kotlin"   // 申明頂層常量

//聲明對象
object UserDAO {
    const val MAX_COUNT = 100 // 對象中的聲明常量 
}

fun main(args: Array<String>) {
    val price: Float = 0.0f 
    val y = 20 
}

 約定: 常量其實就是隻讀變量,編譯期常量(const val)是更爲徹底的常量,一旦編譯之後就不能再修改了。而運行期常(val)還可以根據程序的運行情況初始化。

使用var還是val?

原則: 如果兩種方式都能滿足需求情況下,原則上優先考慮使用val聲明。因爲一方面val聲明的變量是隻讀,一旦初始化後不  能修改,這可以避免程序運行過程中錯誤地修改變量內容;另一方面在聲明引用類型使用val,對象的引用不會被修改,但是
引用內容可以修改,這樣會更加安全,也符合函數式編程的技術要求。

4. 表達式

    val score = 80
    // if控制結構表達式
    val result = if (score < 60) "不及格" else "及格"

    //try表達式
    val score = try {
        //TODO
    } catch (e: Exception) {
        return
    }

5. 類的聲明

data class Order(var id: Long, var date: Date)

6. Unit

如果一個函數的返回類型是Unit,則需要省略。Kotlin的Unit關鍵字相當於Java中的void,表示返回空的數據,用於函數的返回     類型聲明.

7. 基本數據類型

整數類型:Byte、Short、Int和Long,Int是默認類型。
浮點類型:Float和Double,Double是默認類型。
字符類型:Char。
布爾類型:Boolean。

8. 非空類型和可空類型

Kotlin語言,默認情況下所有的數據類型都是非空類型(Non-Null),聲明的變量都是不能接收空值(null)的。

var n: Int = 10
n = null //發生編譯錯誤

Kotlin爲每一種非空類型提供對應的可空類型(Nullable),就是在非空類型後面加上問號(?)表示可空類型。

var n: Int? = 10
n = null //可以接收空值(null)

可空類型在具體使用時會有一些限制:   

不能直接調用可空類型對象的函數或屬性。
不能把可空類型數據賦值給非空類型變量。
不能把可空類型數據傳遞給非空類型參數的函數。

爲了“突破”這些限制,Kotlin提供瞭如下運算符:
安全調用運算符:?.

可空類型變量使用安全調用運算符(?.)可以調用非空類型的函數或屬性。安全調用運算符(?.)會判斷可空類型變量是否爲空,如果是則不會調用函數或屬性,直接返回空值;否則返回調用結果。

fun main(args: Array<String>) {
    
    val divNumber1 = divide(100, 0)
    val result1 = divNumber1?.plus(100)  //divNumber1+100,結果null 
    println(result1)
    val divNumber2 = divide(100, 10)
    val result2 = divNumber2?.plus(100)  //divNumber2+100,結果110.0 
    println(result2)

}

//聲明除法運算函數
fun divide(n1: Int, n2: Int): Double? {
    if (n2 == 0) {//判斷分母是否爲0
        return null
    }
    return n1.toDouble() / n2
}

安全轉換運算符:as?
Elvis運算符:?:

有的時候在可空類型表達式中,當表達式爲空值時,並不希望返回默認的空值,而是其他數值。此時可以使用Elvis運算符          (?:),也稱爲空值合併運算符,Elvis運算符有兩個操作數,假設有表達式:A ?: B,如果A不爲空值則結果爲A;否則結            果爲B。

fun main(args: Array<String>) {
    
    val divNumber1 = divide(100, 0)
    val result1 = divNumber1?.plus(100) ?: 0   //divNumber1+100,結果0 
    println(result1)
    val divNumber2 = divide(100, 10)
    val result2 = divNumber2?.plus(100) ?: 0   //divNumber2+100,結果110.0 
    println(result2)

}

//聲明除法運算函數
fun divide(n1: Int, n2: Int): Double? {
    if (n2 == 0) {//判斷分母是否爲0
        return null
    }
    return n1.toDouble() / n2
}

非空斷言:!!

可空類型變量可以使用非空斷言運算符(!!)調用非空類型的函數或屬性。非空斷言運算符(!!)顧名思義就是斷言可空類          型變量不會爲空,調用過程是存在風險的,如果可空類型變量真的爲空,則會拋出空指針異常;如果非則可以正常調用函            數或屬性。

fun main(args: Array<String>) {
    
    val divNumber1 = divide(100, 10)
    val result1 = divNumber1!!.plus(100)   //divNumber1+100,結果110.0
    println(result1)
    val divNumber2 = divide(100, 0)
    val result2 = divNumber2!!.plus(100)  //divNumber2+100,結果拋出異常 
    println(result2)

}

//聲明除法運算函數
fun divide(n1: Int, n2: Int): Double? {
    if (n2 == 0) {//判斷分母是否爲0
        return null
    }
    return n1.toDouble() / n2
}

此外,還一個let函數幫助處理可空類型數據。

9. 字符串模板

字符串模板是以$開頭,語法如下:

$變量或常量
${表達式} //任何表達式,也可以是單個變量或常量

val age = 18
val s1 = "她的年齡是${age}歲。" //使用表達式形式模板 
println(s1) //她的年齡是18歲。
val score = 'A'
val s2 = "她的英語成績是$score" //使用變量形式模板
println(s2) //她的英語成績是A
val now = java.util.Date()
val s3 = "今天是:${now.year + 1900}年${now.month}月${now.day}日" ③
println(s3)

10 . 其它運算符

冒號(:)。用於變量或常量類型聲明,以及聲明繼承父類和實現接口。
小括號。起到改變表達式運算順序的作用,它的優先級最高。
中括號([])。索引訪問運算符號。
引用號(.)。調用函數或屬性運算符。
賦值號(=)。賦值是用等號運算符(=)進行的。
可空符(?)。標識一個可空類型。
安全調用運算符(?.)。調用非空類型的函數或屬性。
Elvis運算符(?:)。空值合併運算符。
非空斷言(!!)。斷言可空表達式爲非空。
雙冒號(::)。引用類、屬性或函數。
區間(..)。表示一個範圍區間。
箭頭(->)。用來聲明Lambda表達式。
展開運算符(*)。將數組傳遞給可變參數時使用

運算符優先級大體順序,從高到低是:算術運算符→位運算符→關係運算符→邏輯運算符→賦值運算符。

11. 程序流程控制

分支結構:if和when

循環結構:while、do-while和for

跳轉結構:break、continue和return

when多分支結構:

1. when結構當做語句使用

when (表達式) {
    分支條件表達式1 -> {
        語句組1
    }
    分支條件表達式2 -> {
        語句組2
    }
    ...
    分支條件表達式n -> {
        語句組n
    }
    else -> {
        語句組n+1
    }
}
fun main(args: Array<String>) {
    val testScore = 75 //設定一個數值用來測試
    when (testScore / 10) { 
        9 -> { 
            println('優')
        }
        8 -> println('良')
        7, 6 -> println('中') 
        else -> println('差')
    }
    val level = "優" //設定一個數值用來測試
    var desc = "" //接收返回值
    when (level) { 
        "優" -> desc = "90分以上"
        "良" -> desc = "80分~90分"
        "中" -> desc = "70分~80分"
        "差" -> desc = "低於60分"
    }
    println("說明 = " + desc)
}

break 配合標籤使用

label1@ for (x in 0..4) { 
    for (y in 5 downTo 1) { 
        if (y == x) {
            // 跳轉到label1指向的外循環
            break@label1 
        }
        println("(x,y) = ($x,$y)")
    }
}
println("Game Over!")

Kotlin核心庫中有三個閉區間類:IntRange、LongRange和CharRange

區間中的元素只能是整數或字符,不能是浮點、字符串等其他數據類型。

在Kotlin語言中閉區間採用區間運算符(..)表示,而半開區間則需要使用中綴運算符until表示。

fun main(args: Array<String>) {
    for (x in 0..5) { //定義閉區間包含0和5 
        print("$x,")
    }
    println()
    for (x in 0 until 5) { //定義半開區間包含0,不包含5 
        print("$x,")
    }
    println()
    for (x in 'A'..'E') { //定義閉區間包含'A'和'E' 
        print("$x,")
    }
    println()
    for (x in 'A' until 'E') { //定義半開區間包含'A',不包含'E' 
        print("$x,")
    }
}

12. 使用in和!in關鍵字

判斷一個數值是否在區間中可以使用in關鍵字。而!in關鍵字,則是判斷一個值不在區間中。此外,這兩個關鍵字(in和!in)還      可以判斷一個數值是否集合或數組中。

fun main(args: Array<String>) {
    var testscore = 80 //設置一個分數用於測試
    var grade = when (testscore) { 
        in 90..100 -> "優"
        in 80 until 90 -> "良"
        in 60 until 80 -> "中"
        in 0 until 60 -> "差"
        else -> "無"
    } 
    println("Grade = " + grade)
    if (testscore !in 60..100) { //使用!in關鍵字 
        println("不及格")
    }
    val strArray = arrayOf("劉備", "關羽", "張飛")
    val name = "趙雲"
    if (name !in strArray) { 
        println(name + "不在隊伍中")
    }
}

13. 函數

fun 函數名(參數列表) : 返回值類型 {
    函數體
    return 返回值
}

無返回數據與Unit類型

有的函數只是爲了處理某個過程,不需要返回具體數據,例如println函數。此時可以將函數返回類型聲明爲Unit,相當於Java      中的void類型,即表示沒有實際意義的數據。  

fun printArea2(width: Double, height: Double) { //省略Unit 
    val area = width * height
    println("$width x $height 長方形的面積:$area")
    //省略return 
}

永遠不會正常返回數據與Nothing類型

Kotlin中提供一種特殊的數據類型Nothing,Nothing只用於函數返回類型聲明,不能用於變量聲明。Nothing聲明的函數永遠不  會正常的返回,只會拋出異常。

fun readDate(): Nothing {
    throw IOException()
}

提示: 使用Nothing的目的何在?有些框架,例如Junit單元測試框架,在測試失敗時會調用Nothing返回類型的函數,通過它拋出異常使當前測試用例失敗。

注意 Unit與Nothing區別?Unit表示數據沒有實際意義,它可以聲明函數返回類型,也可以聲明變量類型,聲明函數時函數可以正常返回,只是返回數據沒有實際意義。Nothing只能聲明函數返回類型,說明函數永遠不會正常返回,Nothing不能聲
明變量。

可變參數

Kotlin中函數的參數個數可以變化,它可以接受不確定數量的輸入類型參數(這些參數具有相同的類型),有點像是傳遞一個數組。可以通過在參數名前面加vararg關鍵字的方式來表示這是可變參數。

fun sum(vararg numbers: Double, multiple: Int = 1): Double {
    var total = 0.0
    for (number in numbers) {
        total += number
    }
    return total * multiple
}

表達式函數體

fun rectangleArea(width: Double, height: Double) = width * height

Kotlin中的類成員包括:
構造函數
初始化代碼塊
成員函數
屬性
內部類和嵌套類
對象表達式聲明

// 員工類
class Employee {
    var no: Int = 0 // 員工編號屬性
    var job: String? = null // 工作屬性 
    var firstName: String = "Tony" 
    var lastName: String = "Guan" 
    var fullName: String //全名 
        get() { 
            return firstName + "." + lastName
        }
        set (value) { 
            val name = value.split(".") 
            firstName = name[0]
            lastName = name[1]
        }
    var salary: Double = 0.0 // 薪資屬性 
        set(value) {
            if (value >= 0.0) field = value 
        }
}

提示: 屬性本身並不真正的保存數據,數據被保存到支持字段中,支持字段一般是不可見的,支持字段只能應用在屬性訪問器中,通過系統定義好的field變量訪問。

提示: 並不是所有的屬性都有支持字段的,例如上述代碼中的fullName屬性是通過另外屬性計算而來,它沒有支持字段,聲明時不需要初始值。這種屬性有點像是一個函數。這種屬性在Swift語言中稱爲計算屬性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章